diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/media/0010-media-Entities-pads-and-links.patch')
-rw-r--r-- | extras/recipes-kernel/linux/linux-omap/media/0010-media-Entities-pads-and-links.patch | 690 |
1 files changed, 690 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/media/0010-media-Entities-pads-and-links.patch b/extras/recipes-kernel/linux/linux-omap/media/0010-media-Entities-pads-and-links.patch new file mode 100644 index 00000000..be762331 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap/media/0010-media-Entities-pads-and-links.patch | |||
@@ -0,0 +1,690 @@ | |||
1 | From b4697e5a8ad1e564ea378d435c2ce190318c1027 Mon Sep 17 00:00:00 2001 | ||
2 | From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
3 | Date: Wed, 9 Dec 2009 12:40:00 +0100 | ||
4 | Subject: [PATCH 10/43] media: Entities, pads and links | ||
5 | |||
6 | As video hardware pipelines become increasingly complex and | ||
7 | configurable, the current hardware description through v4l2 subdevices | ||
8 | reaches its limits. In addition to enumerating and configuring | ||
9 | subdevices, video camera drivers need a way to discover and modify at | ||
10 | runtime how those subdevices are connected. This is done through new | ||
11 | elements called entities, pads and links. | ||
12 | |||
13 | An entity is a basic media hardware building block. It can correspond to | ||
14 | a large variety of logical blocks such as physical hardware devices | ||
15 | (CMOS sensor for instance), logical hardware devices (a building block | ||
16 | in a System-on-Chip image processing pipeline), DMA channels or physical | ||
17 | connectors. | ||
18 | |||
19 | A pad is a connection endpoint through which an entity can interact with | ||
20 | other entities. Data (not restricted to video) produced by an entity | ||
21 | flows from the entity's output to one or more entity inputs. Pads should | ||
22 | not be confused with physical pins at chip boundaries. | ||
23 | |||
24 | A link is a point-to-point oriented connection between two pads, either | ||
25 | on the same entity or on different entities. Data flows from a source | ||
26 | pad to a sink pad. | ||
27 | |||
28 | Links are stored in the source entity. To make backwards graph walk | ||
29 | faster, a copy of all links is also stored in the sink entity. The copy | ||
30 | is known as a backlink and is only used to help graph traversal. | ||
31 | |||
32 | The entity API is made of three functions: | ||
33 | |||
34 | - media_entity_init() initializes an entity. The caller must provide an | ||
35 | array of pads as well as an estimated number of links. The links array | ||
36 | is allocated dynamically and will be reallocated if it grows beyond the | ||
37 | initial estimate. | ||
38 | |||
39 | - media_entity_cleanup() frees resources allocated for an entity. It | ||
40 | must be called during the cleanup phase after unregistering the entity | ||
41 | and before freeing it. | ||
42 | |||
43 | - media_entity_create_link() creates a link between two entities. An | ||
44 | entry in the link array of each entity is allocated and stores pointers | ||
45 | to source and sink pads. | ||
46 | |||
47 | When a media device is unregistered, all its entities are unregistered | ||
48 | automatically. | ||
49 | |||
50 | The code is based on Hans Verkuil <hverkuil@xs4all.nl> initial work. | ||
51 | |||
52 | Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
53 | Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
54 | --- | ||
55 | Documentation/DocBook/v4l/media-controller.xml | 20 +++ | ||
56 | Documentation/media-framework.txt | 151 ++++++++++++++++++++++++ | ||
57 | drivers/media/Makefile | 2 +- | ||
58 | drivers/media/media-device.c | 56 +++++++++ | ||
59 | drivers/media/media-entity.c | 147 +++++++++++++++++++++++ | ||
60 | include/media/media-device.h | 19 +++ | ||
61 | include/media/media-entity.h | 122 +++++++++++++++++++ | ||
62 | 7 files changed, 516 insertions(+), 1 deletions(-) | ||
63 | create mode 100644 drivers/media/media-entity.c | ||
64 | create mode 100644 include/media/media-entity.h | ||
65 | |||
66 | diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml | ||
67 | index 253ddb4..f89228d 100644 | ||
68 | --- a/Documentation/DocBook/v4l/media-controller.xml | ||
69 | +++ b/Documentation/DocBook/v4l/media-controller.xml | ||
70 | @@ -53,4 +53,24 @@ | ||
71 | implementing policies that belong to userspace.</para> | ||
72 | <para>The media controller API aims at solving those problems.</para> | ||
73 | </section> | ||
74 | + | ||
75 | + <section id="media-controller-model"> | ||
76 | + <title>Media device model</title> | ||
77 | + <para>Discovering a device internal topology, and configuring it at runtime, | ||
78 | + is one of the goals of the media controller API. To achieve this, hardware | ||
79 | + devices are modelled as an oriented graph of building blocks called entities | ||
80 | + connected through pads.</para> | ||
81 | + <para>An entity is a basic media hardware or software building block. It can | ||
82 | + correspond to a large variety of logical blocks such as physical hardware | ||
83 | + devices (CMOS sensor for instance), logical hardware devices (a building | ||
84 | + block in a System-on-Chip image processing pipeline), DMA channels or | ||
85 | + physical connectors.</para> | ||
86 | + <para>A pad is a connection endpoint through which an entity can interact | ||
87 | + with other entities. Data (not restricted to video) produced by an entity | ||
88 | + flows from the entity's output to one or more entity inputs. Pads should not | ||
89 | + be confused with physical pins at chip boundaries.</para> | ||
90 | + <para>A link is a point-to-point oriented connection between two pads, | ||
91 | + either on the same entity or on different entities. Data flows from a source | ||
92 | + pad to a sink pad.</para> | ||
93 | + </section> | ||
94 | </chapter> | ||
95 | diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt | ||
96 | index 1844c3f..b252cf9 100644 | ||
97 | --- a/Documentation/media-framework.txt | ||
98 | +++ b/Documentation/media-framework.txt | ||
99 | @@ -13,6 +13,30 @@ Documentation/DocBook/v4l/media-controller.xml. This document will focus on | ||
100 | the kernel-side implementation of the media framework. | ||
101 | |||
102 | |||
103 | +Abstract media device model | ||
104 | +--------------------------- | ||
105 | + | ||
106 | +Discovering a device internal topology, and configuring it at runtime, is one | ||
107 | +of the goals of the media framework. To achieve this, hardware devices are | ||
108 | +modeled as an oriented graph of building blocks called entities connected | ||
109 | +through pads. | ||
110 | + | ||
111 | +An entity is a basic media hardware building block. It can correspond to | ||
112 | +a large variety of logical blocks such as physical hardware devices | ||
113 | +(CMOS sensor for instance), logical hardware devices (a building block | ||
114 | +in a System-on-Chip image processing pipeline), DMA channels or physical | ||
115 | +connectors. | ||
116 | + | ||
117 | +A pad is a connection endpoint through which an entity can interact with | ||
118 | +other entities. Data (not restricted to video) produced by an entity | ||
119 | +flows from the entity's output to one or more entity inputs. Pads should | ||
120 | +not be confused with physical pins at chip boundaries. | ||
121 | + | ||
122 | +A link is a point-to-point oriented connection between two pads, either | ||
123 | +on the same entity or on different entities. Data flows from a source | ||
124 | +pad to a sink pad. | ||
125 | + | ||
126 | + | ||
127 | Media device | ||
128 | ------------ | ||
129 | |||
130 | @@ -65,3 +89,130 @@ Drivers unregister media device instances by calling | ||
131 | media_device_unregister(struct media_device *mdev); | ||
132 | |||
133 | Unregistering a media device that hasn't been registered is *NOT* safe. | ||
134 | + | ||
135 | + | ||
136 | +Entities, pads and links | ||
137 | +------------------------ | ||
138 | + | ||
139 | +- Entities | ||
140 | + | ||
141 | +Entities are represented by a struct media_entity instance, defined in | ||
142 | +include/media/media-entity.h. The structure is usually embedded into a | ||
143 | +higher-level structure, such as a v4l2_subdev or video_device instance, | ||
144 | +although drivers can allocate entities directly. | ||
145 | + | ||
146 | +Drivers initialize entities by calling | ||
147 | + | ||
148 | + media_entity_init(struct media_entity *entity, u16 num_pads, | ||
149 | + struct media_pad *pads, u16 extra_links); | ||
150 | + | ||
151 | +The media_entity name, type, flags, revision and group_id fields can be | ||
152 | +initialized before or after calling media_entity_init. Entities embedded in | ||
153 | +higher-level standard structures can have some of those fields set by the | ||
154 | +higher-level framework. | ||
155 | + | ||
156 | +As the number of pads is known in advance, the pads array is not allocated | ||
157 | +dynamically but is managed by the entity driver. Most drivers will embed the | ||
158 | +pads array in a driver-specific structure, avoiding dynamic allocation. | ||
159 | + | ||
160 | +Drivers must set the direction of every pad in the pads array before calling | ||
161 | +media_entity_init. The function will initialize the other pads fields. | ||
162 | + | ||
163 | +Unlike the number of pads, the total number of links isn't always known in | ||
164 | +advance by the entity driver. As an initial estimate, media_entity_init | ||
165 | +pre-allocates a number of links equal to the number of pads plus an optional | ||
166 | +number of extra links. The links array will be reallocated if it grows beyond | ||
167 | +the initial estimate. | ||
168 | + | ||
169 | +Drivers register entities with a media device by calling | ||
170 | + | ||
171 | + media_device_register_entity(struct media_device *mdev, | ||
172 | + struct media_entity *entity); | ||
173 | + | ||
174 | +Entities are identified by a unique positive integer ID. Drivers can provide an | ||
175 | +ID by filling the media_entity id field prior to registration, or request the | ||
176 | +media controller framework to assign an ID automatically. Drivers that provide | ||
177 | +IDs manually must ensure that all IDs are unique. IDs are not guaranteed to be | ||
178 | +contiguous even when they are all assigned automatically by the framework. | ||
179 | + | ||
180 | +Drivers unregister entities by calling | ||
181 | + | ||
182 | + media_device_unregister_entity(struct media_entity *entity); | ||
183 | + | ||
184 | +Unregistering an entity will not change the IDs of the other entities, and the | ||
185 | +ID will never be reused for a newly registered entity. | ||
186 | + | ||
187 | +When a media device is unregistered, all its entities are unregistered | ||
188 | +automatically. No manual entities unregistration is then required. | ||
189 | + | ||
190 | +Drivers free resources associated with an entity by calling | ||
191 | + | ||
192 | + media_entity_cleanup(struct media_entity *entity); | ||
193 | + | ||
194 | +This function must be called during the cleanup phase after unregistering the | ||
195 | +entity. Note that the media_entity instance itself must be freed explicitly by | ||
196 | +the driver if required. | ||
197 | + | ||
198 | +Entities have flags that describe the entity capabilities and state. | ||
199 | + | ||
200 | + MEDIA_ENT_FL_DEFAULT indicates the default entity for a given type. | ||
201 | + This can be used to report the default audio and video devices or the | ||
202 | + default camera sensor. | ||
203 | + | ||
204 | +Logical entity groups can be defined by setting the group ID of all member | ||
205 | +entities to the same non-zero value. An entity group serves no purpose in the | ||
206 | +kernel, but is reported to userspace during entities enumeration. The group_id | ||
207 | +field belongs to the media device driver and must not by touched by entity | ||
208 | +drivers. | ||
209 | + | ||
210 | +Media device drivers should define groups if several entities are logically | ||
211 | +bound together. Example usages include reporting | ||
212 | + | ||
213 | + - ALSA, VBI and video nodes that carry the same media stream | ||
214 | + - lens and flash controllers associated with a sensor | ||
215 | + | ||
216 | +- Pads | ||
217 | + | ||
218 | +Pads are represented by a struct media_pad instance, defined in | ||
219 | +include/media/media-entity.h. Each entity stores its pads in a pads array | ||
220 | +managed by the entity driver. Drivers usually embed the array in a | ||
221 | +driver-specific structure. | ||
222 | + | ||
223 | +Pads are identified by their entity and their 0-based index in the pads array. | ||
224 | +Both information are stored in the media_pad structure, making the media_pad | ||
225 | +pointer the canonical way to store and pass link references. | ||
226 | + | ||
227 | +Pads have flags that describe the pad capabilities and state. | ||
228 | + | ||
229 | + MEDIA_PAD_FL_INPUT indicates that the pad supports sinking data. | ||
230 | + MEDIA_PAD_FL_OUTPUT indicates that the pad supports sourcing data. | ||
231 | + | ||
232 | +One and only one of MEDIA_PAD_FL_INPUT and MEDIA_PAD_FL_OUTPUT must be set for | ||
233 | +each pad. | ||
234 | + | ||
235 | +- Links | ||
236 | + | ||
237 | +Links are represented by a struct media_link instance, defined in | ||
238 | +include/media/media-entity.h. Each entity stores all links originating at or | ||
239 | +targetting any of its pads in a links array. A given link is thus stored | ||
240 | +twice, once in the source entity and once in the target entity. The array is | ||
241 | +pre-allocated and grows dynamically as needed. | ||
242 | + | ||
243 | +Drivers create links by calling | ||
244 | + | ||
245 | + media_entity_create_link(struct media_entity *source, u16 source_pad, | ||
246 | + struct media_entity *sink, u16 sink_pad, | ||
247 | + u32 flags); | ||
248 | + | ||
249 | +An entry in the link array of each entity is allocated and stores pointers | ||
250 | +to source and sink pads. | ||
251 | + | ||
252 | +Links have flags that describe the link capabilities and state. | ||
253 | + | ||
254 | + MEDIA_LNK_FL_ENABLED indicates that the link is enabled and can be used | ||
255 | + to transfer media data. When two or more links target a sink pad, only | ||
256 | + one of them can be enabled at a time. | ||
257 | + MEDIA_LNK_FL_IMMUTABLE indicates that the link enabled state can't be | ||
258 | + modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then | ||
259 | + MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always | ||
260 | + enabled. | ||
261 | diff --git a/drivers/media/Makefile b/drivers/media/Makefile | ||
262 | index 019d3e0..b890248 100644 | ||
263 | --- a/drivers/media/Makefile | ||
264 | +++ b/drivers/media/Makefile | ||
265 | @@ -2,7 +2,7 @@ | ||
266 | # Makefile for the kernel multimedia device drivers. | ||
267 | # | ||
268 | |||
269 | -media-objs := media-device.o media-devnode.o | ||
270 | +media-objs := media-device.o media-devnode.o media-entity.o | ||
271 | |||
272 | ifeq ($(CONFIG_MEDIA_CONTROLLER),y) | ||
273 | obj-$(CONFIG_MEDIA_SUPPORT) += media.o | ||
274 | diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c | ||
275 | index 57a9c6b..b8a3ace 100644 | ||
276 | --- a/drivers/media/media-device.c | ||
277 | +++ b/drivers/media/media-device.c | ||
278 | @@ -25,6 +25,7 @@ | ||
279 | |||
280 | #include <media/media-device.h> | ||
281 | #include <media/media-devnode.h> | ||
282 | +#include <media/media-entity.h> | ||
283 | |||
284 | static const struct media_file_operations media_device_fops = { | ||
285 | .owner = THIS_MODULE, | ||
286 | @@ -69,6 +70,10 @@ int __must_check media_device_register(struct media_device *mdev) | ||
287 | if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0)) | ||
288 | return -EINVAL; | ||
289 | |||
290 | + mdev->entity_id = 1; | ||
291 | + INIT_LIST_HEAD(&mdev->entities); | ||
292 | + spin_lock_init(&mdev->lock); | ||
293 | + | ||
294 | /* Register the device node. */ | ||
295 | mdev->devnode.fops = &media_device_fops; | ||
296 | mdev->devnode.parent = mdev->dev; | ||
297 | @@ -94,7 +99,58 @@ EXPORT_SYMBOL_GPL(media_device_register); | ||
298 | */ | ||
299 | void media_device_unregister(struct media_device *mdev) | ||
300 | { | ||
301 | + struct media_entity *entity; | ||
302 | + struct media_entity *next; | ||
303 | + | ||
304 | + list_for_each_entry_safe(entity, next, &mdev->entities, list) | ||
305 | + media_device_unregister_entity(entity); | ||
306 | + | ||
307 | device_remove_file(&mdev->devnode.dev, &dev_attr_model); | ||
308 | media_devnode_unregister(&mdev->devnode); | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(media_device_unregister); | ||
311 | + | ||
312 | +/** | ||
313 | + * media_device_register_entity - Register an entity with a media device | ||
314 | + * @mdev: The media device | ||
315 | + * @entity: The entity | ||
316 | + */ | ||
317 | +int __must_check media_device_register_entity(struct media_device *mdev, | ||
318 | + struct media_entity *entity) | ||
319 | +{ | ||
320 | + /* Warn if we apparently re-register an entity */ | ||
321 | + WARN_ON(entity->parent != NULL); | ||
322 | + entity->parent = mdev; | ||
323 | + | ||
324 | + spin_lock(&mdev->lock); | ||
325 | + if (entity->id == 0) | ||
326 | + entity->id = mdev->entity_id++; | ||
327 | + else | ||
328 | + mdev->entity_id = max(entity->id + 1, mdev->entity_id); | ||
329 | + list_add_tail(&entity->list, &mdev->entities); | ||
330 | + spin_unlock(&mdev->lock); | ||
331 | + | ||
332 | + return 0; | ||
333 | +} | ||
334 | +EXPORT_SYMBOL_GPL(media_device_register_entity); | ||
335 | + | ||
336 | +/** | ||
337 | + * media_device_unregister_entity - Unregister an entity | ||
338 | + * @entity: The entity | ||
339 | + * | ||
340 | + * If the entity has never been registered this function will return | ||
341 | + * immediately. | ||
342 | + */ | ||
343 | +void media_device_unregister_entity(struct media_entity *entity) | ||
344 | +{ | ||
345 | + struct media_device *mdev = entity->parent; | ||
346 | + | ||
347 | + if (mdev == NULL) | ||
348 | + return; | ||
349 | + | ||
350 | + spin_lock(&mdev->lock); | ||
351 | + list_del(&entity->list); | ||
352 | + spin_unlock(&mdev->lock); | ||
353 | + entity->parent = NULL; | ||
354 | +} | ||
355 | +EXPORT_SYMBOL_GPL(media_device_unregister_entity); | ||
356 | diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c | ||
357 | new file mode 100644 | ||
358 | index 0000000..e4ba2bc | ||
359 | --- /dev/null | ||
360 | +++ b/drivers/media/media-entity.c | ||
361 | @@ -0,0 +1,147 @@ | ||
362 | +/* | ||
363 | + * Media entity | ||
364 | + * | ||
365 | + * Copyright (C) 2010 Nokia Corporation | ||
366 | + * | ||
367 | + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
368 | + * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
369 | + * | ||
370 | + * This program is free software; you can redistribute it and/or modify | ||
371 | + * it under the terms of the GNU General Public License version 2 as | ||
372 | + * published by the Free Software Foundation. | ||
373 | + * | ||
374 | + * This program is distributed in the hope that it will be useful, | ||
375 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
376 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
377 | + * GNU General Public License for more details. | ||
378 | + * | ||
379 | + * You should have received a copy of the GNU General Public License | ||
380 | + * along with this program; if not, write to the Free Software | ||
381 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
382 | + */ | ||
383 | + | ||
384 | +#include <linux/module.h> | ||
385 | +#include <linux/slab.h> | ||
386 | +#include <media/media-entity.h> | ||
387 | + | ||
388 | +/** | ||
389 | + * media_entity_init - Initialize a media entity | ||
390 | + * | ||
391 | + * @num_pads: Total number of input and output pads. | ||
392 | + * @extra_links: Initial estimate of the number of extra links. | ||
393 | + * @pads: Array of 'num_pads' pads. | ||
394 | + * | ||
395 | + * The total number of pads is an intrinsic property of entities known by the | ||
396 | + * entity driver, while the total number of links depends on hardware design | ||
397 | + * and is an extrinsic property unknown to the entity driver. However, in most | ||
398 | + * use cases the entity driver can guess the number of links which can safely | ||
399 | + * be assumed to be equal to or larger than the number of pads. | ||
400 | + * | ||
401 | + * For those reasons the links array can be preallocated based on the entity | ||
402 | + * driver guess and will be reallocated later if extra links need to be | ||
403 | + * created. | ||
404 | + * | ||
405 | + * This function allocates a links array with enough space to hold at least | ||
406 | + * 'num_pads' + 'extra_links' elements. The media_entity::max_links field will | ||
407 | + * be set to the number of allocated elements. | ||
408 | + * | ||
409 | + * The pads array is managed by the entity driver and passed to | ||
410 | + * media_entity_init() where its pointer will be stored in the entity structure. | ||
411 | + */ | ||
412 | +int | ||
413 | +media_entity_init(struct media_entity *entity, u16 num_pads, | ||
414 | + struct media_pad *pads, u16 extra_links) | ||
415 | +{ | ||
416 | + struct media_link *links; | ||
417 | + unsigned int max_links = num_pads + extra_links; | ||
418 | + unsigned int i; | ||
419 | + | ||
420 | + links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL); | ||
421 | + if (links == NULL) | ||
422 | + return -ENOMEM; | ||
423 | + | ||
424 | + entity->group_id = 0; | ||
425 | + entity->max_links = max_links; | ||
426 | + entity->num_links = 0; | ||
427 | + entity->num_backlinks = 0; | ||
428 | + entity->num_pads = num_pads; | ||
429 | + entity->pads = pads; | ||
430 | + entity->links = links; | ||
431 | + | ||
432 | + for (i = 0; i < num_pads; i++) { | ||
433 | + pads[i].entity = entity; | ||
434 | + pads[i].index = i; | ||
435 | + } | ||
436 | + | ||
437 | + return 0; | ||
438 | +} | ||
439 | +EXPORT_SYMBOL_GPL(media_entity_init); | ||
440 | + | ||
441 | +void | ||
442 | +media_entity_cleanup(struct media_entity *entity) | ||
443 | +{ | ||
444 | + kfree(entity->links); | ||
445 | +} | ||
446 | +EXPORT_SYMBOL_GPL(media_entity_cleanup); | ||
447 | + | ||
448 | +static struct media_link *media_entity_add_link(struct media_entity *entity) | ||
449 | +{ | ||
450 | + if (entity->num_links >= entity->max_links) { | ||
451 | + struct media_link *links = entity->links; | ||
452 | + unsigned int max_links = entity->max_links + 2; | ||
453 | + unsigned int i; | ||
454 | + | ||
455 | + links = krealloc(links, max_links * sizeof(*links), GFP_KERNEL); | ||
456 | + if (links == NULL) | ||
457 | + return NULL; | ||
458 | + | ||
459 | + for (i = 0; i < entity->num_links; i++) | ||
460 | + links[i].reverse->reverse = &links[i]; | ||
461 | + | ||
462 | + entity->max_links = max_links; | ||
463 | + entity->links = links; | ||
464 | + } | ||
465 | + | ||
466 | + return &entity->links[entity->num_links++]; | ||
467 | +} | ||
468 | + | ||
469 | +int | ||
470 | +media_entity_create_link(struct media_entity *source, u16 source_pad, | ||
471 | + struct media_entity *sink, u16 sink_pad, u32 flags) | ||
472 | +{ | ||
473 | + struct media_link *link; | ||
474 | + struct media_link *backlink; | ||
475 | + | ||
476 | + BUG_ON(source == NULL || sink == NULL); | ||
477 | + BUG_ON(source_pad >= source->num_pads); | ||
478 | + BUG_ON(sink_pad >= sink->num_pads); | ||
479 | + | ||
480 | + link = media_entity_add_link(source); | ||
481 | + if (link == NULL) | ||
482 | + return -ENOMEM; | ||
483 | + | ||
484 | + link->source = &source->pads[source_pad]; | ||
485 | + link->sink = &sink->pads[sink_pad]; | ||
486 | + link->flags = flags; | ||
487 | + | ||
488 | + /* Create the backlink. Backlinks are used to help graph traversal and | ||
489 | + * are not reported to userspace. | ||
490 | + */ | ||
491 | + backlink = media_entity_add_link(sink); | ||
492 | + if (backlink == NULL) { | ||
493 | + source->num_links--; | ||
494 | + return -ENOMEM; | ||
495 | + } | ||
496 | + | ||
497 | + backlink->source = &source->pads[source_pad]; | ||
498 | + backlink->sink = &sink->pads[sink_pad]; | ||
499 | + backlink->flags = flags; | ||
500 | + | ||
501 | + link->reverse = backlink; | ||
502 | + backlink->reverse = link; | ||
503 | + | ||
504 | + sink->num_backlinks++; | ||
505 | + | ||
506 | + return 0; | ||
507 | +} | ||
508 | +EXPORT_SYMBOL_GPL(media_entity_create_link); | ||
509 | diff --git a/include/media/media-device.h b/include/media/media-device.h | ||
510 | index e11f01a..0b1ecf5 100644 | ||
511 | --- a/include/media/media-device.h | ||
512 | +++ b/include/media/media-device.h | ||
513 | @@ -25,8 +25,10 @@ | ||
514 | |||
515 | #include <linux/device.h> | ||
516 | #include <linux/list.h> | ||
517 | +#include <linux/spinlock.h> | ||
518 | |||
519 | #include <media/media-devnode.h> | ||
520 | +#include <media/media-entity.h> | ||
521 | |||
522 | /** | ||
523 | * struct media_device - Media device | ||
524 | @@ -37,6 +39,9 @@ | ||
525 | * @bus_info: Unique and stable device location identifier | ||
526 | * @hw_revision: Hardware device revision | ||
527 | * @driver_version: Device driver version | ||
528 | + * @entity_id: ID of the next entity to be registered | ||
529 | + * @entities: List of registered entities | ||
530 | + * @lock: Entities list lock | ||
531 | * | ||
532 | * This structure represents an abstract high-level media device. It allows easy | ||
533 | * access to entities and provides basic media device-level support. The | ||
534 | @@ -58,6 +63,12 @@ struct media_device { | ||
535 | char bus_info[32]; | ||
536 | u32 hw_revision; | ||
537 | u32 driver_version; | ||
538 | + | ||
539 | + u32 entity_id; | ||
540 | + struct list_head entities; | ||
541 | + | ||
542 | + /* Protects the entities list */ | ||
543 | + spinlock_t lock; | ||
544 | }; | ||
545 | |||
546 | /* media_devnode to media_device */ | ||
547 | @@ -66,4 +77,12 @@ struct media_device { | ||
548 | int __must_check media_device_register(struct media_device *mdev); | ||
549 | void media_device_unregister(struct media_device *mdev); | ||
550 | |||
551 | +int __must_check media_device_register_entity(struct media_device *mdev, | ||
552 | + struct media_entity *entity); | ||
553 | +void media_device_unregister_entity(struct media_entity *entity); | ||
554 | + | ||
555 | +/* Iterate over all entities. */ | ||
556 | +#define media_device_for_each_entity(entity, mdev) \ | ||
557 | + list_for_each_entry(entity, &(mdev)->entities, list) | ||
558 | + | ||
559 | #endif | ||
560 | diff --git a/include/media/media-entity.h b/include/media/media-entity.h | ||
561 | new file mode 100644 | ||
562 | index 0000000..7cf9135 | ||
563 | --- /dev/null | ||
564 | +++ b/include/media/media-entity.h | ||
565 | @@ -0,0 +1,122 @@ | ||
566 | +/* | ||
567 | + * Media entity | ||
568 | + * | ||
569 | + * Copyright (C) 2010 Nokia Corporation | ||
570 | + * | ||
571 | + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
572 | + * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
573 | + * | ||
574 | + * This program is free software; you can redistribute it and/or modify | ||
575 | + * it under the terms of the GNU General Public License version 2 as | ||
576 | + * published by the Free Software Foundation. | ||
577 | + * | ||
578 | + * This program is distributed in the hope that it will be useful, | ||
579 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
580 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
581 | + * GNU General Public License for more details. | ||
582 | + * | ||
583 | + * You should have received a copy of the GNU General Public License | ||
584 | + * along with this program; if not, write to the Free Software | ||
585 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
586 | + */ | ||
587 | + | ||
588 | +#ifndef _MEDIA_ENTITY_H | ||
589 | +#define _MEDIA_ENTITY_H | ||
590 | + | ||
591 | +#include <linux/list.h> | ||
592 | + | ||
593 | +#define MEDIA_ENT_TYPE_SHIFT 16 | ||
594 | +#define MEDIA_ENT_TYPE_MASK 0x00ff0000 | ||
595 | +#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff | ||
596 | + | ||
597 | +#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENTITY_TYPE_SHIFT) | ||
598 | +#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENTITY_T_DEVNODE + 1) | ||
599 | +#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENTITY_T_DEVNODE + 2) | ||
600 | +#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENTITY_T_DEVNODE + 3) | ||
601 | +#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENTITY_T_DEVNODE + 4) | ||
602 | + | ||
603 | +#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENTITY_TYPE_SHIFT) | ||
604 | +#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENTITY_T_V4L2_SUBDEV + 1) | ||
605 | +#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENTITY_T_V4L2_SUBDEV + 2) | ||
606 | +#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENTITY_T_V4L2_SUBDEV + 3) | ||
607 | + | ||
608 | +#define MEDIA_ENT_FL_DEFAULT (1 << 0) | ||
609 | + | ||
610 | +#define MEDIA_LNK_FL_ENABLED (1 << 0) | ||
611 | +#define MEDIA_LNK_FL_IMMUTABLE (1 << 1) | ||
612 | + | ||
613 | +#define MEDIA_PAD_FL_INPUT (1 << 0) | ||
614 | +#define MEDIA_PAD_FL_OUTPUT (1 << 1) | ||
615 | + | ||
616 | +struct media_link { | ||
617 | + struct media_pad *source; /* Source pad */ | ||
618 | + struct media_pad *sink; /* Sink pad */ | ||
619 | + struct media_link *reverse; /* Link in the reverse direction */ | ||
620 | + unsigned long flags; /* Link flags (MEDIA_LNK_FL_*) */ | ||
621 | +}; | ||
622 | + | ||
623 | +struct media_pad { | ||
624 | + struct media_entity *entity; /* Entity this pad belongs to */ | ||
625 | + u16 index; /* Pad index in the entity pads array */ | ||
626 | + unsigned long flags; /* Pad flags (MEDIA_PAD_FL_*) */ | ||
627 | +}; | ||
628 | + | ||
629 | +struct media_entity { | ||
630 | + struct list_head list; | ||
631 | + struct media_device *parent; /* Media device this entity belongs to*/ | ||
632 | + u32 id; /* Entity ID, unique in the parent media | ||
633 | + * device context */ | ||
634 | + const char *name; /* Entity name */ | ||
635 | + u32 type; /* Entity type (MEDIA_ENT_T_*) */ | ||
636 | + u32 revision; /* Entity revision, driver specific */ | ||
637 | + unsigned long flags; /* Entity flags (MEDIA_ENT_FL_*) */ | ||
638 | + u32 group_id; /* Entity group ID */ | ||
639 | + | ||
640 | + u16 num_pads; /* Number of input and output pads */ | ||
641 | + u16 num_links; /* Number of existing links, both | ||
642 | + * enabled and disabled */ | ||
643 | + u16 num_backlinks; /* Number of backlinks */ | ||
644 | + u16 max_links; /* Maximum number of links */ | ||
645 | + | ||
646 | + struct media_pad *pads; /* Pads array (num_pads elements) */ | ||
647 | + struct media_link *links; /* Links array (max_links elements)*/ | ||
648 | + | ||
649 | + union { | ||
650 | + /* Node specifications */ | ||
651 | + struct { | ||
652 | + u32 major; | ||
653 | + u32 minor; | ||
654 | + } v4l; | ||
655 | + struct { | ||
656 | + u32 major; | ||
657 | + u32 minor; | ||
658 | + } fb; | ||
659 | + struct { | ||
660 | + u32 card; | ||
661 | + u32 device; | ||
662 | + u32 subdevice; | ||
663 | + } alsa; | ||
664 | + int dvb; | ||
665 | + | ||
666 | + /* Sub-device specifications */ | ||
667 | + /* Nothing needed yet */ | ||
668 | + }; | ||
669 | +}; | ||
670 | + | ||
671 | +static inline u32 media_entity_type(struct media_entity *entity) | ||
672 | +{ | ||
673 | + return entity->type & MEDIA_ENT_TYPE_MASK; | ||
674 | +} | ||
675 | + | ||
676 | +static inline u32 media_entity_subtype(struct media_entity *entity) | ||
677 | +{ | ||
678 | + return entity->type & MEDIA_ENT_SUBTYPE_MASK; | ||
679 | +} | ||
680 | + | ||
681 | +int media_entity_init(struct media_entity *entity, u16 num_pads, | ||
682 | + struct media_pad *pads, u16 extra_links); | ||
683 | +void media_entity_cleanup(struct media_entity *entity); | ||
684 | +int media_entity_create_link(struct media_entity *source, u16 source_pad, | ||
685 | + struct media_entity *sink, u16 sink_pad, u32 flags); | ||
686 | + | ||
687 | +#endif | ||
688 | -- | ||
689 | 1.6.6.1 | ||
690 | |||