4 * Copyright (C) 2010 Nokia Corporation
6 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7 * Sakari Ailus <sakari.ailus@iki.fi>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/types.h>
24 #include <linux/ioctl.h>
25 #include <linux/media.h>
27 #include <media/media-device.h>
28 #include <media/media-devnode.h>
29 #include <media/media-entity.h>
31 /* -----------------------------------------------------------------------------
35 static int media_device_open(struct file
*filp
)
40 static int media_device_close(struct file
*filp
)
45 static int media_device_get_info(struct media_device
*dev
,
46 struct media_device_info __user
*__info
)
48 struct media_device_info info
;
50 memset(&info
, 0, sizeof(info
));
52 strlcpy(info
.driver
, dev
->dev
->driver
->name
, sizeof(info
.driver
));
53 strlcpy(info
.model
, dev
->model
, sizeof(info
.model
));
54 strlcpy(info
.serial
, dev
->serial
, sizeof(info
.serial
));
55 strlcpy(info
.bus_info
, dev
->bus_info
, sizeof(info
.bus_info
));
57 info
.media_version
= MEDIA_API_VERSION
;
58 info
.hw_revision
= dev
->hw_revision
;
59 info
.driver_version
= dev
->driver_version
;
61 return copy_to_user(__info
, &info
, sizeof(*__info
));
64 static long media_device_ioctl(struct file
*filp
, unsigned int cmd
,
67 struct media_devnode
*devnode
= media_devnode_data(filp
);
68 struct media_device
*dev
= to_media_device(devnode
);
72 case MEDIA_IOC_DEVICE_INFO
:
73 ret
= media_device_get_info(dev
,
74 (struct media_device_info __user
*)arg
);
84 static const struct media_file_operations media_device_fops
= {
86 .open
= media_device_open
,
87 .ioctl
= media_device_ioctl
,
88 .release
= media_device_close
,
91 /* -----------------------------------------------------------------------------
95 static ssize_t
show_model(struct device
*cd
,
96 struct device_attribute
*attr
, char *buf
)
98 struct media_device
*mdev
= to_media_device(to_media_devnode(cd
));
100 return sprintf(buf
, "%.*s\n", (int)sizeof(mdev
->model
), mdev
->model
);
103 static DEVICE_ATTR(model
, S_IRUGO
, show_model
, NULL
);
105 /* -----------------------------------------------------------------------------
106 * Registration/unregistration
109 static void media_device_release(struct media_devnode
*mdev
)
114 * media_device_register - register a media device
115 * @mdev: The media device
117 * The caller is responsible for initializing the media device before
118 * registration. The following fields must be set:
120 * - dev must point to the parent device
121 * - model must be filled with the device model name
123 int __must_check
media_device_register(struct media_device
*mdev
)
127 if (WARN_ON(mdev
->dev
== NULL
|| mdev
->model
[0] == 0))
131 INIT_LIST_HEAD(&mdev
->entities
);
132 spin_lock_init(&mdev
->lock
);
133 mutex_init(&mdev
->graph_mutex
);
135 /* Register the device node. */
136 mdev
->devnode
.fops
= &media_device_fops
;
137 mdev
->devnode
.parent
= mdev
->dev
;
138 mdev
->devnode
.release
= media_device_release
;
139 ret
= media_devnode_register(&mdev
->devnode
);
143 ret
= device_create_file(&mdev
->devnode
.dev
, &dev_attr_model
);
145 media_devnode_unregister(&mdev
->devnode
);
151 EXPORT_SYMBOL_GPL(media_device_register
);
154 * media_device_unregister - unregister a media device
155 * @mdev: The media device
158 void media_device_unregister(struct media_device
*mdev
)
160 struct media_entity
*entity
;
161 struct media_entity
*next
;
163 list_for_each_entry_safe(entity
, next
, &mdev
->entities
, list
)
164 media_device_unregister_entity(entity
);
166 device_remove_file(&mdev
->devnode
.dev
, &dev_attr_model
);
167 media_devnode_unregister(&mdev
->devnode
);
169 EXPORT_SYMBOL_GPL(media_device_unregister
);
172 * media_device_register_entity - Register an entity with a media device
173 * @mdev: The media device
174 * @entity: The entity
176 int __must_check
media_device_register_entity(struct media_device
*mdev
,
177 struct media_entity
*entity
)
179 /* Warn if we apparently re-register an entity */
180 WARN_ON(entity
->parent
!= NULL
);
181 entity
->parent
= mdev
;
183 spin_lock(&mdev
->lock
);
185 entity
->id
= mdev
->entity_id
++;
187 mdev
->entity_id
= max(entity
->id
+ 1, mdev
->entity_id
);
188 list_add_tail(&entity
->list
, &mdev
->entities
);
189 spin_unlock(&mdev
->lock
);
193 EXPORT_SYMBOL_GPL(media_device_register_entity
);
196 * media_device_unregister_entity - Unregister an entity
197 * @entity: The entity
199 * If the entity has never been registered this function will return
202 void media_device_unregister_entity(struct media_entity
*entity
)
204 struct media_device
*mdev
= entity
->parent
;
209 spin_lock(&mdev
->lock
);
210 list_del(&entity
->list
);
211 spin_unlock(&mdev
->lock
);
212 entity
->parent
= NULL
;
214 EXPORT_SYMBOL_GPL(media_device_unregister_entity
);