1176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart/* 2176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * Media device 3176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * 4176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * Copyright (C) 2010 Nokia Corporation 5176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * 6176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com> 7176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * Sakari Ailus <sakari.ailus@iki.fi> 8176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * 9176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * This program is free software; you can redistribute it and/or modify 10176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * it under the terms of the GNU General Public License version 2 as 11176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * published by the Free Software Foundation. 12176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * 13176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * This program is distributed in the hope that it will be useful, 14176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * but WITHOUT ANY WARRANTY; without even the implied warranty of 15176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * GNU General Public License for more details. 17176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * 18176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * You should have received a copy of the GNU General Public License 19176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * along with this program; if not, write to the Free Software 20176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart */ 22176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 23176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart#include <linux/types.h> 24176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart#include <linux/ioctl.h> 25140d88165c25137e871f9559e67986ed89251105Laurent Pinchart#include <linux/media.h> 2635a246363ec41e7b19f7887a97ef3d01ab41356aPaul Gortmaker#include <linux/export.h> 27176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 28176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart#include <media/media-device.h> 29176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart#include <media/media-devnode.h> 3053e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart#include <media/media-entity.h> 31176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 32140d88165c25137e871f9559e67986ed89251105Laurent Pinchart/* ----------------------------------------------------------------------------- 33140d88165c25137e871f9559e67986ed89251105Laurent Pinchart * Userspace API 34140d88165c25137e871f9559e67986ed89251105Laurent Pinchart */ 35140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 36140d88165c25137e871f9559e67986ed89251105Laurent Pinchartstatic int media_device_open(struct file *filp) 37140d88165c25137e871f9559e67986ed89251105Laurent Pinchart{ 38140d88165c25137e871f9559e67986ed89251105Laurent Pinchart return 0; 39140d88165c25137e871f9559e67986ed89251105Laurent Pinchart} 40140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 41140d88165c25137e871f9559e67986ed89251105Laurent Pinchartstatic int media_device_close(struct file *filp) 42140d88165c25137e871f9559e67986ed89251105Laurent Pinchart{ 43140d88165c25137e871f9559e67986ed89251105Laurent Pinchart return 0; 44140d88165c25137e871f9559e67986ed89251105Laurent Pinchart} 45140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 46140d88165c25137e871f9559e67986ed89251105Laurent Pinchartstatic int media_device_get_info(struct media_device *dev, 47140d88165c25137e871f9559e67986ed89251105Laurent Pinchart struct media_device_info __user *__info) 48140d88165c25137e871f9559e67986ed89251105Laurent Pinchart{ 49140d88165c25137e871f9559e67986ed89251105Laurent Pinchart struct media_device_info info; 50140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 51140d88165c25137e871f9559e67986ed89251105Laurent Pinchart memset(&info, 0, sizeof(info)); 52140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 53140d88165c25137e871f9559e67986ed89251105Laurent Pinchart strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver)); 54140d88165c25137e871f9559e67986ed89251105Laurent Pinchart strlcpy(info.model, dev->model, sizeof(info.model)); 55140d88165c25137e871f9559e67986ed89251105Laurent Pinchart strlcpy(info.serial, dev->serial, sizeof(info.serial)); 56140d88165c25137e871f9559e67986ed89251105Laurent Pinchart strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info)); 57140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 58140d88165c25137e871f9559e67986ed89251105Laurent Pinchart info.media_version = MEDIA_API_VERSION; 59140d88165c25137e871f9559e67986ed89251105Laurent Pinchart info.hw_revision = dev->hw_revision; 60140d88165c25137e871f9559e67986ed89251105Laurent Pinchart info.driver_version = dev->driver_version; 61140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 62140d88165c25137e871f9559e67986ed89251105Laurent Pinchart return copy_to_user(__info, &info, sizeof(*__info)); 63140d88165c25137e871f9559e67986ed89251105Laurent Pinchart} 64140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 651651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchartstatic struct media_entity *find_entity(struct media_device *mdev, u32 id) 661651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart{ 671651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_entity *entity; 681651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart int next = id & MEDIA_ENT_ID_FLAG_NEXT; 691651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 701651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart id &= ~MEDIA_ENT_ID_FLAG_NEXT; 711651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 721651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart spin_lock(&mdev->lock); 731651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 741651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart media_device_for_each_entity(entity, mdev) { 751651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if ((entity->id == id && !next) || 761651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart (entity->id > id && next)) { 771651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart spin_unlock(&mdev->lock); 781651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return entity; 791651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart } 801651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart } 811651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 821651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart spin_unlock(&mdev->lock); 831651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 841651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return NULL; 851651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart} 861651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 871651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchartstatic long media_device_enum_entities(struct media_device *mdev, 881651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_entity_desc __user *uent) 891651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart{ 901651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_entity *ent; 911651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_entity_desc u_ent; 921651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 931651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id))) 941651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return -EFAULT; 951651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 961651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart ent = find_entity(mdev, u_ent.id); 971651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 981651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (ent == NULL) 991651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return -EINVAL; 1001651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1011651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart u_ent.id = ent->id; 1021651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart u_ent.name[0] = '\0'; 1031651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (ent->name) 1041651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart strlcpy(u_ent.name, ent->name, sizeof(u_ent.name)); 1051651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart u_ent.type = ent->type; 1061651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart u_ent.revision = ent->revision; 1071651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart u_ent.flags = ent->flags; 1081651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart u_ent.group_id = ent->group_id; 1091651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart u_ent.pads = ent->num_pads; 1101651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart u_ent.links = ent->num_links - ent->num_backlinks; 111fa5034c667c224be48db31a0d043dba305e8e7a8Clemens Ladisch memcpy(&u_ent.raw, &ent->info, sizeof(ent->info)); 1121651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (copy_to_user(uent, &u_ent, sizeof(u_ent))) 1131651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return -EFAULT; 1141651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return 0; 1151651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart} 1161651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1171651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchartstatic void media_device_kpad_to_upad(const struct media_pad *kpad, 1181651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_pad_desc *upad) 1191651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart{ 1201651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart upad->entity = kpad->entity->id; 1211651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart upad->index = kpad->index; 1221651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart upad->flags = kpad->flags; 1231651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart} 1241651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1251651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchartstatic long media_device_enum_links(struct media_device *mdev, 1261651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_links_enum __user *ulinks) 1271651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart{ 1281651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_entity *entity; 1291651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_links_enum links; 1301651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1311651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (copy_from_user(&links, ulinks, sizeof(links))) 1321651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return -EFAULT; 1331651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1341651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart entity = find_entity(mdev, links.entity); 1351651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (entity == NULL) 1361651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return -EINVAL; 1371651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1381651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (links.pads) { 1391651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart unsigned int p; 1401651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1411651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart for (p = 0; p < entity->num_pads; p++) { 1421651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_pad_desc pad; 1431651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart media_device_kpad_to_upad(&entity->pads[p], &pad); 1441651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (copy_to_user(&links.pads[p], &pad, sizeof(pad))) 1451651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return -EFAULT; 1461651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart } 1471651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart } 1481651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1491651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (links.links) { 1501651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_link_desc __user *ulink; 1511651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart unsigned int l; 1521651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1531651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart for (l = 0, ulink = links.links; l < entity->num_links; l++) { 1541651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart struct media_link_desc link; 1551651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1561651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart /* Ignore backlinks. */ 1571651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (entity->links[l].source->entity != entity) 1581651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart continue; 1591651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 1601651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart media_device_kpad_to_upad(entity->links[l].source, 1611651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart &link.source); 1621651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart media_device_kpad_to_upad(entity->links[l].sink, 1631651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart &link.sink); 1641651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart link.flags = entity->links[l].flags; 1651651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (copy_to_user(ulink, &link, sizeof(*ulink))) 1661651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return -EFAULT; 1671651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart ulink++; 1681651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart } 1691651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart } 1701651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart if (copy_to_user(ulinks, &links, sizeof(*ulinks))) 1711651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return -EFAULT; 1721651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart return 0; 1731651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart} 1741651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 17597548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchartstatic long media_device_setup_link(struct media_device *mdev, 17697548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart struct media_link_desc __user *_ulink) 17797548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart{ 17897548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart struct media_link *link = NULL; 17997548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart struct media_link_desc ulink; 18097548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart struct media_entity *source; 18197548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart struct media_entity *sink; 18297548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart int ret; 18397548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 18497548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart if (copy_from_user(&ulink, _ulink, sizeof(ulink))) 18597548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart return -EFAULT; 18697548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 18797548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart /* Find the source and sink entities and link. 18897548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart */ 18997548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart source = find_entity(mdev, ulink.source.entity); 19097548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart sink = find_entity(mdev, ulink.sink.entity); 19197548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 19297548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart if (source == NULL || sink == NULL) 19397548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart return -EINVAL; 19497548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 19597548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart if (ulink.source.index >= source->num_pads || 19697548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart ulink.sink.index >= sink->num_pads) 19797548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart return -EINVAL; 19897548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 19997548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart link = media_entity_find_link(&source->pads[ulink.source.index], 20097548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart &sink->pads[ulink.sink.index]); 20197548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart if (link == NULL) 20297548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart return -EINVAL; 20397548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 20497548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart /* Setup the link on both entities. */ 20597548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart ret = __media_entity_setup_link(link, ulink.flags); 20697548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 20797548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart if (copy_to_user(_ulink, &ulink, sizeof(ulink))) 20897548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart return -EFAULT; 20997548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 21097548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart return ret; 21197548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart} 21297548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 213140d88165c25137e871f9559e67986ed89251105Laurent Pinchartstatic long media_device_ioctl(struct file *filp, unsigned int cmd, 214140d88165c25137e871f9559e67986ed89251105Laurent Pinchart unsigned long arg) 215140d88165c25137e871f9559e67986ed89251105Laurent Pinchart{ 216140d88165c25137e871f9559e67986ed89251105Laurent Pinchart struct media_devnode *devnode = media_devnode_data(filp); 217140d88165c25137e871f9559e67986ed89251105Laurent Pinchart struct media_device *dev = to_media_device(devnode); 218140d88165c25137e871f9559e67986ed89251105Laurent Pinchart long ret; 219140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 220140d88165c25137e871f9559e67986ed89251105Laurent Pinchart switch (cmd) { 221140d88165c25137e871f9559e67986ed89251105Laurent Pinchart case MEDIA_IOC_DEVICE_INFO: 222140d88165c25137e871f9559e67986ed89251105Laurent Pinchart ret = media_device_get_info(dev, 223140d88165c25137e871f9559e67986ed89251105Laurent Pinchart (struct media_device_info __user *)arg); 224140d88165c25137e871f9559e67986ed89251105Laurent Pinchart break; 225140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 2261651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart case MEDIA_IOC_ENUM_ENTITIES: 2271651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart ret = media_device_enum_entities(dev, 2281651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart (struct media_entity_desc __user *)arg); 2291651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart break; 2301651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 2311651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart case MEDIA_IOC_ENUM_LINKS: 2321651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart mutex_lock(&dev->graph_mutex); 2331651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart ret = media_device_enum_links(dev, 2341651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart (struct media_links_enum __user *)arg); 2351651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart mutex_unlock(&dev->graph_mutex); 2361651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart break; 2371651333b09743887bc2dd3d158a11853a2be3fe7Laurent Pinchart 23897548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart case MEDIA_IOC_SETUP_LINK: 23997548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart mutex_lock(&dev->graph_mutex); 24097548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart ret = media_device_setup_link(dev, 24197548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart (struct media_link_desc __user *)arg); 24297548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart mutex_unlock(&dev->graph_mutex); 24397548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart break; 24497548ed4c4661502cdfd1aabd5d3876fa4f5cc2eLaurent Pinchart 245140d88165c25137e871f9559e67986ed89251105Laurent Pinchart default: 246140d88165c25137e871f9559e67986ed89251105Laurent Pinchart ret = -ENOIOCTLCMD; 247140d88165c25137e871f9559e67986ed89251105Laurent Pinchart } 248140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 249140d88165c25137e871f9559e67986ed89251105Laurent Pinchart return ret; 250140d88165c25137e871f9559e67986ed89251105Laurent Pinchart} 251140d88165c25137e871f9559e67986ed89251105Laurent Pinchart 252176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchartstatic const struct media_file_operations media_device_fops = { 253176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart .owner = THIS_MODULE, 254140d88165c25137e871f9559e67986ed89251105Laurent Pinchart .open = media_device_open, 255140d88165c25137e871f9559e67986ed89251105Laurent Pinchart .ioctl = media_device_ioctl, 256140d88165c25137e871f9559e67986ed89251105Laurent Pinchart .release = media_device_close, 257176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart}; 258176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 259176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart/* ----------------------------------------------------------------------------- 260176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * sysfs 261176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart */ 262176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 263176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchartstatic ssize_t show_model(struct device *cd, 264176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart struct device_attribute *attr, char *buf) 265176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart{ 266176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart struct media_device *mdev = to_media_device(to_media_devnode(cd)); 267176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 268176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model); 269176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart} 270176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 271176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchartstatic DEVICE_ATTR(model, S_IRUGO, show_model, NULL); 272176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 273176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart/* ----------------------------------------------------------------------------- 274176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * Registration/unregistration 275176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart */ 276176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 277176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchartstatic void media_device_release(struct media_devnode *mdev) 278176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart{ 279176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart} 280176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 281176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart/** 282176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * media_device_register - register a media device 283176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * @mdev: The media device 284176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * 285176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * The caller is responsible for initializing the media device before 286176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * registration. The following fields must be set: 287176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * 288176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * - dev must point to the parent device 289176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * - model must be filled with the device model name 290176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart */ 291176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchartint __must_check media_device_register(struct media_device *mdev) 292176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart{ 293176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart int ret; 294176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 295176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0)) 296176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart return -EINVAL; 297176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 29853e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart mdev->entity_id = 1; 29953e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart INIT_LIST_HEAD(&mdev->entities); 30053e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart spin_lock_init(&mdev->lock); 301503c3d829eaf48837dd5bff5d97ad66369bb955aLaurent Pinchart mutex_init(&mdev->graph_mutex); 30253e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 303176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart /* Register the device node. */ 304176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart mdev->devnode.fops = &media_device_fops; 305176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart mdev->devnode.parent = mdev->dev; 306176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart mdev->devnode.release = media_device_release; 307176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart ret = media_devnode_register(&mdev->devnode); 308176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart if (ret < 0) 309176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart return ret; 310176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 311176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart ret = device_create_file(&mdev->devnode.dev, &dev_attr_model); 312176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart if (ret < 0) { 313176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart media_devnode_unregister(&mdev->devnode); 314176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart return ret; 315176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart } 316176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 317176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart return 0; 318176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart} 319176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent PinchartEXPORT_SYMBOL_GPL(media_device_register); 320176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart 321176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart/** 322176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * media_device_unregister - unregister a media device 323176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * @mdev: The media device 324176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart * 325176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart */ 326176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchartvoid media_device_unregister(struct media_device *mdev) 327176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart{ 32853e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart struct media_entity *entity; 32953e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart struct media_entity *next; 33053e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 33153e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart list_for_each_entry_safe(entity, next, &mdev->entities, list) 33253e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart media_device_unregister_entity(entity); 33353e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 334176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart device_remove_file(&mdev->devnode.dev, &dev_attr_model); 335176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart media_devnode_unregister(&mdev->devnode); 336176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent Pinchart} 337176fb0d108f7495ccf9aa127e1342a1a0d87e004Laurent PinchartEXPORT_SYMBOL_GPL(media_device_unregister); 33853e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 33953e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart/** 34053e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart * media_device_register_entity - Register an entity with a media device 34153e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart * @mdev: The media device 34253e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart * @entity: The entity 34353e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart */ 34453e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchartint __must_check media_device_register_entity(struct media_device *mdev, 34553e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart struct media_entity *entity) 34653e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart{ 34753e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart /* Warn if we apparently re-register an entity */ 34853e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart WARN_ON(entity->parent != NULL); 34953e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart entity->parent = mdev; 35053e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 35153e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart spin_lock(&mdev->lock); 35253e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart if (entity->id == 0) 35353e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart entity->id = mdev->entity_id++; 35453e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart else 35553e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart mdev->entity_id = max(entity->id + 1, mdev->entity_id); 35653e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart list_add_tail(&entity->list, &mdev->entities); 35753e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart spin_unlock(&mdev->lock); 35853e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 35953e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart return 0; 36053e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart} 36153e269c102fbaf77e7dc526b1606ad4a48e57200Laurent PinchartEXPORT_SYMBOL_GPL(media_device_register_entity); 36253e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 36353e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart/** 36453e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart * media_device_unregister_entity - Unregister an entity 36553e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart * @entity: The entity 36653e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart * 36753e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart * If the entity has never been registered this function will return 36853e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart * immediately. 36953e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart */ 37053e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchartvoid media_device_unregister_entity(struct media_entity *entity) 37153e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart{ 37253e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart struct media_device *mdev = entity->parent; 37353e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 37453e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart if (mdev == NULL) 37553e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart return; 37653e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart 37753e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart spin_lock(&mdev->lock); 37853e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart list_del(&entity->list); 37953e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart spin_unlock(&mdev->lock); 38053e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart entity->parent = NULL; 38153e269c102fbaf77e7dc526b1606ad4a48e57200Laurent Pinchart} 38253e269c102fbaf77e7dc526b1606ad4a48e57200Laurent PinchartEXPORT_SYMBOL_GPL(media_device_unregister_entity); 383