diff options
130 files changed, 5237 insertions, 1849 deletions
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 7b3fcc5effcd..cdd8b24db68d 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl | |||
@@ -263,6 +263,7 @@ X!Isound/sound_firmware.c | |||
263 | !Iinclude/media/lirc_dev.h | 263 | !Iinclude/media/lirc_dev.h |
264 | </sect1> | 264 | </sect1> |
265 | <sect1><title>Media Controller devices</title> | 265 | <sect1><title>Media Controller devices</title> |
266 | !Pinclude/media/media-device.h Media Controller | ||
266 | !Iinclude/media/media-device.h | 267 | !Iinclude/media/media-device.h |
267 | !Iinclude/media/media-devnode.h | 268 | !Iinclude/media/media-devnode.h |
268 | !Iinclude/media/media-entity.h | 269 | !Iinclude/media/media-entity.h |
diff --git a/Documentation/DocBook/media/v4l/media-controller.xml b/Documentation/DocBook/media/v4l/media-controller.xml index 873ac3a621f0..5f2fc07a93d7 100644 --- a/Documentation/DocBook/media/v4l/media-controller.xml +++ b/Documentation/DocBook/media/v4l/media-controller.xml | |||
@@ -58,21 +58,36 @@ | |||
58 | <title>Media device model</title> | 58 | <title>Media device model</title> |
59 | <para>Discovering a device internal topology, and configuring it at runtime, | 59 | <para>Discovering a device internal topology, and configuring it at runtime, |
60 | is one of the goals of the media controller API. To achieve this, hardware | 60 | is one of the goals of the media controller API. To achieve this, hardware |
61 | devices are modelled as an oriented graph of building blocks called entities | 61 | devices and Linux Kernel interfaces are modelled as graph objects on |
62 | connected through pads.</para> | 62 | an oriented graph. The object types that constitute the graph are:</para> |
63 | <para>An entity is a basic media hardware or software building block. It can | 63 | <itemizedlist> |
64 | correspond to a large variety of logical blocks such as physical hardware | 64 | <listitem><para>An <emphasis role="bold">entity</emphasis> |
65 | devices (CMOS sensor for instance), logical hardware devices (a building | 65 | is a basic media hardware or software building block. It can correspond to |
66 | block in a System-on-Chip image processing pipeline), DMA channels or | 66 | a large variety of logical blocks such as physical hardware devices |
67 | physical connectors.</para> | 67 | (CMOS sensor for instance), logical hardware devices (a building block in |
68 | <para>A pad is a connection endpoint through which an entity can interact | 68 | a System-on-Chip image processing pipeline), DMA channels or physical |
69 | with other entities. Data (not restricted to video) produced by an entity | 69 | connectors.</para></listitem> |
70 | flows from the entity's output to one or more entity inputs. Pads should not | 70 | <listitem><para>An <emphasis role="bold">interface</emphasis> |
71 | be confused with physical pins at chip boundaries.</para> | 71 | is a graph representation of a Linux Kernel userspace API interface, |
72 | <para>A link is a point-to-point oriented connection between two pads, | 72 | like a device node or a sysfs file that controls one or more entities |
73 | either on the same entity or on different entities. Data flows from a source | 73 | in the graph.</para></listitem> |
74 | pad to a sink pad.</para> | 74 | <listitem><para>A <emphasis role="bold">pad</emphasis> |
75 | is a data connection endpoint through which an entity can interact with | ||
76 | other entities. Data (not restricted to video) produced by an entity | ||
77 | flows from the entity's output to one or more entity inputs. Pads should | ||
78 | not be confused with physical pins at chip boundaries.</para></listitem> | ||
79 | <listitem><para>A <emphasis role="bold">data link</emphasis> | ||
80 | is a point-to-point oriented connection between two pads, either on the | ||
81 | same entity or on different entities. Data flows from a source pad to a | ||
82 | sink pad.</para></listitem> | ||
83 | <listitem><para>An <emphasis role="bold">interface link</emphasis> | ||
84 | is a point-to-point bidirectional control connection between a Linux | ||
85 | Kernel interface and an entity.m</para></listitem> | ||
86 | </itemizedlist> | ||
75 | </section> | 87 | </section> |
88 | |||
89 | <!-- All non-ioctl specific data types go here. --> | ||
90 | &sub-media-types; | ||
76 | </chapter> | 91 | </chapter> |
77 | 92 | ||
78 | <appendix id="media-user-func"> | 93 | <appendix id="media-user-func"> |
@@ -83,6 +98,7 @@ | |||
83 | &sub-media-func-ioctl; | 98 | &sub-media-func-ioctl; |
84 | <!-- All ioctls go here. --> | 99 | <!-- All ioctls go here. --> |
85 | &sub-media-ioc-device-info; | 100 | &sub-media-ioc-device-info; |
101 | &sub-media-ioc-g-topology; | ||
86 | &sub-media-ioc-enum-entities; | 102 | &sub-media-ioc-enum-entities; |
87 | &sub-media-ioc-enum-links; | 103 | &sub-media-ioc-enum-links; |
88 | &sub-media-ioc-setup-link; | 104 | &sub-media-ioc-setup-link; |
diff --git a/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml b/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml index 5872f8bbf774..0c4f96bfc2de 100644 --- a/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml +++ b/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml | |||
@@ -59,15 +59,6 @@ | |||
59 | <para>Entity IDs can be non-contiguous. Applications must | 59 | <para>Entity IDs can be non-contiguous. Applications must |
60 | <emphasis>not</emphasis> try to enumerate entities by calling | 60 | <emphasis>not</emphasis> try to enumerate entities by calling |
61 | MEDIA_IOC_ENUM_ENTITIES with increasing id's until they get an error.</para> | 61 | MEDIA_IOC_ENUM_ENTITIES with increasing id's until they get an error.</para> |
62 | <para>Two or more entities that share a common non-zero | ||
63 | <structfield>group_id</structfield> value are considered as logically | ||
64 | grouped. Groups are used to report | ||
65 | <itemizedlist> | ||
66 | <listitem><para>ALSA, VBI and video nodes that carry the same media | ||
67 | stream</para></listitem> | ||
68 | <listitem><para>lens and flash controllers associated with a sensor</para></listitem> | ||
69 | </itemizedlist> | ||
70 | </para> | ||
71 | 62 | ||
72 | <table pgwide="1" frame="none" id="media-entity-desc"> | 63 | <table pgwide="1" frame="none" id="media-entity-desc"> |
73 | <title>struct <structname>media_entity_desc</structname></title> | 64 | <title>struct <structname>media_entity_desc</structname></title> |
@@ -106,7 +97,7 @@ | |||
106 | <entry><structfield>revision</structfield></entry> | 97 | <entry><structfield>revision</structfield></entry> |
107 | <entry></entry> | 98 | <entry></entry> |
108 | <entry></entry> | 99 | <entry></entry> |
109 | <entry>Entity revision in a driver/hardware specific format.</entry> | 100 | <entry>Entity revision. Always zero (obsolete)</entry> |
110 | </row> | 101 | </row> |
111 | <row> | 102 | <row> |
112 | <entry>__u32</entry> | 103 | <entry>__u32</entry> |
@@ -120,7 +111,7 @@ | |||
120 | <entry><structfield>group_id</structfield></entry> | 111 | <entry><structfield>group_id</structfield></entry> |
121 | <entry></entry> | 112 | <entry></entry> |
122 | <entry></entry> | 113 | <entry></entry> |
123 | <entry>Entity group ID</entry> | 114 | <entry>Entity group ID. Always zero (obsolete)</entry> |
124 | </row> | 115 | </row> |
125 | <row> | 116 | <row> |
126 | <entry>__u16</entry> | 117 | <entry>__u16</entry> |
@@ -171,97 +162,6 @@ | |||
171 | </tbody> | 162 | </tbody> |
172 | </tgroup> | 163 | </tgroup> |
173 | </table> | 164 | </table> |
174 | |||
175 | <table frame="none" pgwide="1" id="media-entity-type"> | ||
176 | <title>Media entity types</title> | ||
177 | <tgroup cols="2"> | ||
178 | <colspec colname="c1"/> | ||
179 | <colspec colname="c2"/> | ||
180 | <tbody valign="top"> | ||
181 | <row> | ||
182 | <entry><constant>MEDIA_ENT_T_DEVNODE</constant></entry> | ||
183 | <entry>Unknown device node</entry> | ||
184 | </row> | ||
185 | <row> | ||
186 | <entry><constant>MEDIA_ENT_T_DEVNODE_V4L</constant></entry> | ||
187 | <entry>V4L video, radio or vbi device node</entry> | ||
188 | </row> | ||
189 | <row> | ||
190 | <entry><constant>MEDIA_ENT_T_DEVNODE_FB</constant></entry> | ||
191 | <entry>Frame buffer device node</entry> | ||
192 | </row> | ||
193 | <row> | ||
194 | <entry><constant>MEDIA_ENT_T_DEVNODE_ALSA</constant></entry> | ||
195 | <entry>ALSA card</entry> | ||
196 | </row> | ||
197 | <row> | ||
198 | <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_FE</constant></entry> | ||
199 | <entry>DVB frontend devnode</entry> | ||
200 | </row> | ||
201 | <row> | ||
202 | <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DEMUX</constant></entry> | ||
203 | <entry>DVB demux devnode</entry> | ||
204 | </row> | ||
205 | <row> | ||
206 | <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DVR</constant></entry> | ||
207 | <entry>DVB DVR devnode</entry> | ||
208 | </row> | ||
209 | <row> | ||
210 | <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_CA</constant></entry> | ||
211 | <entry>DVB CAM devnode</entry> | ||
212 | </row> | ||
213 | <row> | ||
214 | <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_NET</constant></entry> | ||
215 | <entry>DVB network devnode</entry> | ||
216 | </row> | ||
217 | <row> | ||
218 | <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV</constant></entry> | ||
219 | <entry>Unknown V4L sub-device</entry> | ||
220 | </row> | ||
221 | <row> | ||
222 | <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_SENSOR</constant></entry> | ||
223 | <entry>Video sensor</entry> | ||
224 | </row> | ||
225 | <row> | ||
226 | <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_FLASH</constant></entry> | ||
227 | <entry>Flash controller</entry> | ||
228 | </row> | ||
229 | <row> | ||
230 | <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_LENS</constant></entry> | ||
231 | <entry>Lens controller</entry> | ||
232 | </row> | ||
233 | <row> | ||
234 | <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_DECODER</constant></entry> | ||
235 | <entry>Video decoder, the basic function of the video decoder is to | ||
236 | accept analogue video from a wide variety of sources such as | ||
237 | broadcast, DVD players, cameras and video cassette recorders, in | ||
238 | either NTSC, PAL or HD format and still occasionally SECAM, separate | ||
239 | it into its component parts, luminance and chrominance, and output | ||
240 | it in some digital video standard, with appropriate embedded timing | ||
241 | signals.</entry> | ||
242 | </row> | ||
243 | <row> | ||
244 | <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_TUNER</constant></entry> | ||
245 | <entry>TV and/or radio tuner</entry> | ||
246 | </row> | ||
247 | </tbody> | ||
248 | </tgroup> | ||
249 | </table> | ||
250 | |||
251 | <table frame="none" pgwide="1" id="media-entity-flag"> | ||
252 | <title>Media entity flags</title> | ||
253 | <tgroup cols="2"> | ||
254 | <colspec colname="c1"/> | ||
255 | <colspec colname="c2"/> | ||
256 | <tbody valign="top"> | ||
257 | <row> | ||
258 | <entry><constant>MEDIA_ENT_FL_DEFAULT</constant></entry> | ||
259 | <entry>Default entity for its type. Used to discover the default | ||
260 | audio, VBI and video devices, the default camera sensor, ...</entry> | ||
261 | </row> | ||
262 | </tbody> | ||
263 | </tgroup> | ||
264 | </table> | ||
265 | </refsect1> | 165 | </refsect1> |
266 | 166 | ||
267 | <refsect1> | 167 | <refsect1> |
diff --git a/Documentation/DocBook/media/v4l/media-ioc-enum-links.xml b/Documentation/DocBook/media/v4l/media-ioc-enum-links.xml index 74fb394ec667..2bbeea9f3e18 100644 --- a/Documentation/DocBook/media/v4l/media-ioc-enum-links.xml +++ b/Documentation/DocBook/media/v4l/media-ioc-enum-links.xml | |||
@@ -118,35 +118,6 @@ | |||
118 | </tgroup> | 118 | </tgroup> |
119 | </table> | 119 | </table> |
120 | 120 | ||
121 | <table frame="none" pgwide="1" id="media-pad-flag"> | ||
122 | <title>Media pad flags</title> | ||
123 | <tgroup cols="2"> | ||
124 | <colspec colname="c1"/> | ||
125 | <colspec colname="c2"/> | ||
126 | <tbody valign="top"> | ||
127 | <row> | ||
128 | <entry><constant>MEDIA_PAD_FL_SINK</constant></entry> | ||
129 | <entry>Input pad, relative to the entity. Input pads sink data and | ||
130 | are targets of links.</entry> | ||
131 | </row> | ||
132 | <row> | ||
133 | <entry><constant>MEDIA_PAD_FL_SOURCE</constant></entry> | ||
134 | <entry>Output pad, relative to the entity. Output pads source data | ||
135 | and are origins of links.</entry> | ||
136 | </row> | ||
137 | <row> | ||
138 | <entry><constant>MEDIA_PAD_FL_MUST_CONNECT</constant></entry> | ||
139 | <entry>If this flag is set and the pad is linked to any other | ||
140 | pad, then at least one of those links must be enabled for the | ||
141 | entity to be able to stream. There could be temporary reasons | ||
142 | (e.g. device configuration dependent) for the pad to need | ||
143 | enabled links even when this flag isn't set; the absence of the | ||
144 | flag doesn't imply there is none.</entry> | ||
145 | </row> | ||
146 | </tbody> | ||
147 | </tgroup> | ||
148 | </table> | ||
149 | |||
150 | <table pgwide="1" frame="none" id="media-link-desc"> | 121 | <table pgwide="1" frame="none" id="media-link-desc"> |
151 | <title>struct <structname>media_link_desc</structname></title> | 122 | <title>struct <structname>media_link_desc</structname></title> |
152 | <tgroup cols="3"> | 123 | <tgroup cols="3"> |
@@ -171,33 +142,6 @@ | |||
171 | </tgroup> | 142 | </tgroup> |
172 | </table> | 143 | </table> |
173 | 144 | ||
174 | <table frame="none" pgwide="1" id="media-link-flag"> | ||
175 | <title>Media link flags</title> | ||
176 | <tgroup cols="2"> | ||
177 | <colspec colname="c1"/> | ||
178 | <colspec colname="c2"/> | ||
179 | <tbody valign="top"> | ||
180 | <row> | ||
181 | <entry><constant>MEDIA_LNK_FL_ENABLED</constant></entry> | ||
182 | <entry>The link is enabled and can be used to transfer media data. | ||
183 | When two or more links target a sink pad, only one of them can be | ||
184 | enabled at a time.</entry> | ||
185 | </row> | ||
186 | <row> | ||
187 | <entry><constant>MEDIA_LNK_FL_IMMUTABLE</constant></entry> | ||
188 | <entry>The link enabled state can't be modified at runtime. An | ||
189 | immutable link is always enabled.</entry> | ||
190 | </row> | ||
191 | <row> | ||
192 | <entry><constant>MEDIA_LNK_FL_DYNAMIC</constant></entry> | ||
193 | <entry>The link enabled state can be modified during streaming. This | ||
194 | flag is set by drivers and is read-only for applications.</entry> | ||
195 | </row> | ||
196 | </tbody> | ||
197 | </tgroup> | ||
198 | </table> | ||
199 | <para>One and only one of <constant>MEDIA_PAD_FL_SINK</constant> and | ||
200 | <constant>MEDIA_PAD_FL_SOURCE</constant> must be set for every pad.</para> | ||
201 | </refsect1> | 145 | </refsect1> |
202 | 146 | ||
203 | <refsect1> | 147 | <refsect1> |
diff --git a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml new file mode 100644 index 000000000000..63152ab9efba --- /dev/null +++ b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml | |||
@@ -0,0 +1,394 @@ | |||
1 | <refentry id="media-g-topology"> | ||
2 | <refmeta> | ||
3 | <refentrytitle>ioctl MEDIA_IOC_G_TOPOLOGY</refentrytitle> | ||
4 | &manvol; | ||
5 | </refmeta> | ||
6 | |||
7 | <refnamediv> | ||
8 | <refname>MEDIA_IOC_G_TOPOLOGY</refname> | ||
9 | <refpurpose>Enumerate the graph topology and graph element properties</refpurpose> | ||
10 | </refnamediv> | ||
11 | |||
12 | <refsynopsisdiv> | ||
13 | <funcsynopsis> | ||
14 | <funcprototype> | ||
15 | <funcdef>int <function>ioctl</function></funcdef> | ||
16 | <paramdef>int <parameter>fd</parameter></paramdef> | ||
17 | <paramdef>int <parameter>request</parameter></paramdef> | ||
18 | <paramdef>struct media_v2_topology *<parameter>argp</parameter></paramdef> | ||
19 | </funcprototype> | ||
20 | </funcsynopsis> | ||
21 | </refsynopsisdiv> | ||
22 | |||
23 | <refsect1> | ||
24 | <title>Arguments</title> | ||
25 | |||
26 | <variablelist> | ||
27 | <varlistentry> | ||
28 | <term><parameter>fd</parameter></term> | ||
29 | <listitem> | ||
30 | <para>File descriptor returned by | ||
31 | <link linkend='media-func-open'><function>open()</function></link>.</para> | ||
32 | </listitem> | ||
33 | </varlistentry> | ||
34 | <varlistentry> | ||
35 | <term><parameter>request</parameter></term> | ||
36 | <listitem> | ||
37 | <para>MEDIA_IOC_G_TOPOLOGY</para> | ||
38 | </listitem> | ||
39 | </varlistentry> | ||
40 | <varlistentry> | ||
41 | <term><parameter>argp</parameter></term> | ||
42 | <listitem> | ||
43 | <para></para> | ||
44 | </listitem> | ||
45 | </varlistentry> | ||
46 | </variablelist> | ||
47 | </refsect1> | ||
48 | |||
49 | <refsect1> | ||
50 | <title>Description</title> | ||
51 | |||
52 | <para><emphasis role="bold">NOTE:</emphasis> This new ioctl is programmed to be added on Kernel 4.6. Its definition/arguments may change until its final version.</para> | ||
53 | |||
54 | <para>The typical usage of this ioctl is to call it twice. | ||
55 | On the first call, the structure defined at &media-v2-topology; should | ||
56 | be zeroed. At return, if no errors happen, this ioctl will return the | ||
57 | <constant>topology_version</constant> and the total number of entities, | ||
58 | interfaces, pads and links.</para> | ||
59 | <para>Before the second call, the userspace should allocate arrays to | ||
60 | store the graph elements that are desired, putting the pointers to them | ||
61 | at the ptr_entities, ptr_interfaces, ptr_links and/or ptr_pads, keeping | ||
62 | the other values untouched.</para> | ||
63 | <para>If the <constant>topology_version</constant> remains the same, the | ||
64 | ioctl should fill the desired arrays with the media graph elements.</para> | ||
65 | |||
66 | <table pgwide="1" frame="none" id="media-v2-topology"> | ||
67 | <title>struct <structname>media_v2_topology</structname></title> | ||
68 | <tgroup cols="5"> | ||
69 | <colspec colname="c1" /> | ||
70 | <colspec colname="c2" /> | ||
71 | <colspec colname="c3" /> | ||
72 | <colspec colname="c4" /> | ||
73 | <colspec colname="c5" /> | ||
74 | <tbody valign="top"> | ||
75 | <row> | ||
76 | <entry>__u64</entry> | ||
77 | <entry><structfield>topology_version</structfield></entry> | ||
78 | <entry></entry> | ||
79 | <entry></entry> | ||
80 | <entry>Version of the media graph topology. When the graph is | ||
81 | created, this field starts with zero. Every time a graph | ||
82 | element is added or removed, this field is | ||
83 | incremented.</entry> | ||
84 | </row> | ||
85 | <row> | ||
86 | <entry>__u64</entry> | ||
87 | <entry><structfield>num_entities</structfield></entry> | ||
88 | <entry></entry> | ||
89 | <entry></entry> | ||
90 | <entry>Number of entities in the graph</entry> | ||
91 | </row> | ||
92 | <row> | ||
93 | <entry>__u64</entry> | ||
94 | <entry><structfield>ptr_entities</structfield></entry> | ||
95 | <entry></entry> | ||
96 | <entry></entry> | ||
97 | <entry>A pointer to a memory area where the entities array | ||
98 | will be stored, converted to a 64-bits integer. | ||
99 | It can be zero. if zero, the ioctl won't store the | ||
100 | entities. It will just update | ||
101 | <constant>num_entities</constant></entry> | ||
102 | </row> | ||
103 | <row> | ||
104 | <entry>__u64</entry> | ||
105 | <entry><structfield>num_interfaces</structfield></entry> | ||
106 | <entry></entry> | ||
107 | <entry></entry> | ||
108 | <entry>Number of interfaces in the graph</entry> | ||
109 | </row> | ||
110 | <row> | ||
111 | <entry>__u64</entry> | ||
112 | <entry><structfield>ptr_interfaces</structfield></entry> | ||
113 | <entry></entry> | ||
114 | <entry></entry> | ||
115 | <entry>A pointer to a memory area where the interfaces array | ||
116 | will be stored, converted to a 64-bits integer. | ||
117 | It can be zero. if zero, the ioctl won't store the | ||
118 | interfaces. It will just update | ||
119 | <constant>num_interfaces</constant></entry> | ||
120 | </row> | ||
121 | <row> | ||
122 | <entry>__u64</entry> | ||
123 | <entry><structfield>num_pads</structfield></entry> | ||
124 | <entry></entry> | ||
125 | <entry></entry> | ||
126 | <entry>Total number of pads in the graph</entry> | ||
127 | </row> | ||
128 | <row> | ||
129 | <entry>__u64</entry> | ||
130 | <entry><structfield>ptr_pads</structfield></entry> | ||
131 | <entry></entry> | ||
132 | <entry></entry> | ||
133 | <entry>A pointer to a memory area where the pads array | ||
134 | will be stored, converted to a 64-bits integer. | ||
135 | It can be zero. if zero, the ioctl won't store the | ||
136 | pads. It will just update | ||
137 | <constant>num_pads</constant></entry> | ||
138 | </row> | ||
139 | <row> | ||
140 | <entry>__u64</entry> | ||
141 | <entry><structfield>num_links</structfield></entry> | ||
142 | <entry></entry> | ||
143 | <entry></entry> | ||
144 | <entry>Total number of data and interface links in the graph</entry> | ||
145 | </row> | ||
146 | <row> | ||
147 | <entry>__u64</entry> | ||
148 | <entry><structfield>ptr_links</structfield></entry> | ||
149 | <entry></entry> | ||
150 | <entry></entry> | ||
151 | <entry>A pointer to a memory area where the links array | ||
152 | will be stored, converted to a 64-bits integer. | ||
153 | It can be zero. if zero, the ioctl won't store the | ||
154 | links. It will just update | ||
155 | <constant>num_links</constant></entry> | ||
156 | </row> | ||
157 | </tbody> | ||
158 | </tgroup> | ||
159 | </table> | ||
160 | |||
161 | <table pgwide="1" frame="none" id="media-v2-entity"> | ||
162 | <title>struct <structname>media_v2_entity</structname></title> | ||
163 | <tgroup cols="5"> | ||
164 | <colspec colname="c1" /> | ||
165 | <colspec colname="c2" /> | ||
166 | <colspec colname="c3" /> | ||
167 | <colspec colname="c4" /> | ||
168 | <colspec colname="c5" /> | ||
169 | <tbody valign="top"> | ||
170 | <row> | ||
171 | <entry>__u32</entry> | ||
172 | <entry><structfield>id</structfield></entry> | ||
173 | <entry></entry> | ||
174 | <entry></entry> | ||
175 | <entry>Unique ID for the entity.</entry> | ||
176 | </row> | ||
177 | <row> | ||
178 | <entry>char</entry> | ||
179 | <entry><structfield>name</structfield>[64]</entry> | ||
180 | <entry></entry> | ||
181 | <entry></entry> | ||
182 | <entry>Entity name as an UTF-8 NULL-terminated string.</entry> | ||
183 | </row> | ||
184 | <row> | ||
185 | <entry>__u32</entry> | ||
186 | <entry><structfield>function</structfield></entry> | ||
187 | <entry></entry> | ||
188 | <entry></entry> | ||
189 | <entry>Entity main function, see <xref linkend="media-entity-type" /> for details.</entry> | ||
190 | </row> | ||
191 | <row> | ||
192 | <entry>__u32</entry> | ||
193 | <entry><structfield>reserved</structfield>[12]</entry> | ||
194 | <entry>Reserved for future extensions. Drivers and applications must | ||
195 | set this array to zero.</entry> | ||
196 | </row> | ||
197 | </tbody> | ||
198 | </tgroup> | ||
199 | </table> | ||
200 | |||
201 | <table pgwide="1" frame="none" id="media-v2-interface"> | ||
202 | <title>struct <structname>media_v2_interface</structname></title> | ||
203 | <tgroup cols="5"> | ||
204 | <colspec colname="c1" /> | ||
205 | <colspec colname="c2" /> | ||
206 | <colspec colname="c3" /> | ||
207 | <colspec colname="c4" /> | ||
208 | <colspec colname="c5" /> | ||
209 | <tbody valign="top"> | ||
210 | <row> | ||
211 | <entry>__u32</entry> | ||
212 | <entry><structfield>id</structfield></entry> | ||
213 | <entry></entry> | ||
214 | <entry></entry> | ||
215 | <entry>Unique ID for the interface.</entry> | ||
216 | </row> | ||
217 | <row> | ||
218 | <entry>__u32</entry> | ||
219 | <entry><structfield>intf_type</structfield></entry> | ||
220 | <entry></entry> | ||
221 | <entry></entry> | ||
222 | <entry>Interface type, see <xref linkend="media-intf-type" /> for details.</entry> | ||
223 | </row> | ||
224 | <row> | ||
225 | <entry>__u32</entry> | ||
226 | <entry><structfield>flags</structfield></entry> | ||
227 | <entry></entry> | ||
228 | <entry></entry> | ||
229 | <entry>Interface flags. Currently unused.</entry> | ||
230 | </row> | ||
231 | <row> | ||
232 | <entry>__u32</entry> | ||
233 | <entry><structfield>reserved</structfield>[9]</entry> | ||
234 | <entry></entry> | ||
235 | <entry></entry> | ||
236 | <entry>Reserved for future extensions. Drivers and applications must | ||
237 | set this array to zero.</entry> | ||
238 | </row> | ||
239 | <row> | ||
240 | <entry>struct media_v2_intf_devnode</entry> | ||
241 | <entry><structfield>devnode</structfield></entry> | ||
242 | <entry></entry> | ||
243 | <entry></entry> | ||
244 | <entry>Used only for device node interfaces. See <xref linkend="media-v2-intf-devnode" /> for details..</entry> | ||
245 | </row> | ||
246 | </tbody> | ||
247 | </tgroup> | ||
248 | </table> | ||
249 | |||
250 | <table pgwide="1" frame="none" id="media-v2-intf-devnode"> | ||
251 | <title>struct <structname>media_v2_interface</structname></title> | ||
252 | <tgroup cols="5"> | ||
253 | <colspec colname="c1" /> | ||
254 | <colspec colname="c2" /> | ||
255 | <colspec colname="c3" /> | ||
256 | <colspec colname="c4" /> | ||
257 | <colspec colname="c5" /> | ||
258 | <tbody valign="top"> | ||
259 | <row> | ||
260 | <entry>__u32</entry> | ||
261 | <entry><structfield>major</structfield></entry> | ||
262 | <entry></entry> | ||
263 | <entry></entry> | ||
264 | <entry>Device node major number.</entry> | ||
265 | </row> | ||
266 | <row> | ||
267 | <entry>__u32</entry> | ||
268 | <entry><structfield>minor</structfield></entry> | ||
269 | <entry></entry> | ||
270 | <entry></entry> | ||
271 | <entry>Device node minor number.</entry> | ||
272 | </row> | ||
273 | </tbody> | ||
274 | </tgroup> | ||
275 | </table> | ||
276 | |||
277 | <table pgwide="1" frame="none" id="media-v2-pad"> | ||
278 | <title>struct <structname>media_v2_pad</structname></title> | ||
279 | <tgroup cols="5"> | ||
280 | <colspec colname="c1" /> | ||
281 | <colspec colname="c2" /> | ||
282 | <colspec colname="c3" /> | ||
283 | <colspec colname="c4" /> | ||
284 | <colspec colname="c5" /> | ||
285 | <tbody valign="top"> | ||
286 | <row> | ||
287 | <entry>__u32</entry> | ||
288 | <entry><structfield>id</structfield></entry> | ||
289 | <entry></entry> | ||
290 | <entry></entry> | ||
291 | <entry>Unique ID for the pad.</entry> | ||
292 | </row> | ||
293 | <row> | ||
294 | <entry>__u32</entry> | ||
295 | <entry><structfield>entity_id</structfield></entry> | ||
296 | <entry></entry> | ||
297 | <entry></entry> | ||
298 | <entry>Unique ID for the entity where this pad belongs.</entry> | ||
299 | </row> | ||
300 | <row> | ||
301 | <entry>__u32</entry> | ||
302 | <entry><structfield>flags</structfield></entry> | ||
303 | <entry></entry> | ||
304 | <entry></entry> | ||
305 | <entry>Pad flags, see <xref linkend="media-pad-flag" /> for more details.</entry> | ||
306 | </row> | ||
307 | <row> | ||
308 | <entry>__u32</entry> | ||
309 | <entry><structfield>reserved</structfield>[9]</entry> | ||
310 | <entry></entry> | ||
311 | <entry></entry> | ||
312 | <entry>Reserved for future extensions. Drivers and applications must | ||
313 | set this array to zero.</entry> | ||
314 | </row> | ||
315 | </tbody> | ||
316 | </tgroup> | ||
317 | </table> | ||
318 | |||
319 | <table pgwide="1" frame="none" id="media-v2-link"> | ||
320 | <title>struct <structname>media_v2_pad</structname></title> | ||
321 | <tgroup cols="5"> | ||
322 | <colspec colname="c1" /> | ||
323 | <colspec colname="c2" /> | ||
324 | <colspec colname="c3" /> | ||
325 | <colspec colname="c4" /> | ||
326 | <colspec colname="c5" /> | ||
327 | <tbody valign="top"> | ||
328 | <row> | ||
329 | <entry>__u32</entry> | ||
330 | <entry><structfield>id</structfield></entry> | ||
331 | <entry></entry> | ||
332 | <entry></entry> | ||
333 | <entry>Unique ID for the pad.</entry> | ||
334 | </row> | ||
335 | <row> | ||
336 | <entry>__u32</entry> | ||
337 | <entry><structfield>source_id</structfield></entry> | ||
338 | <entry></entry> | ||
339 | <entry></entry> | ||
340 | <entry> | ||
341 | <para>On pad to pad links: unique ID for the source pad.</para> | ||
342 | <para>On interface to entity links: unique ID for the interface.</para> | ||
343 | </entry> | ||
344 | </row> | ||
345 | <row> | ||
346 | <entry>__u32</entry> | ||
347 | <entry><structfield>sink_id</structfield></entry> | ||
348 | <entry></entry> | ||
349 | <entry></entry> | ||
350 | <entry> | ||
351 | <para>On pad to pad links: unique ID for the sink pad.</para> | ||
352 | <para>On interface to entity links: unique ID for the entity.</para> | ||
353 | </entry> | ||
354 | </row> | ||
355 | <row> | ||
356 | <entry>__u32</entry> | ||
357 | <entry><structfield>flags</structfield></entry> | ||
358 | <entry></entry> | ||
359 | <entry></entry> | ||
360 | <entry>Link flags, see <xref linkend="media-link-flag" /> for more details.</entry> | ||
361 | </row> | ||
362 | <row> | ||
363 | <entry>__u32</entry> | ||
364 | <entry><structfield>reserved</structfield>[5]</entry> | ||
365 | <entry></entry> | ||
366 | <entry></entry> | ||
367 | <entry>Reserved for future extensions. Drivers and applications must | ||
368 | set this array to zero.</entry> | ||
369 | </row> | ||
370 | </tbody> | ||
371 | </tgroup> | ||
372 | </table> | ||
373 | |||
374 | </refsect1> | ||
375 | |||
376 | <refsect1> | ||
377 | &return-value; | ||
378 | |||
379 | <variablelist> | ||
380 | <varlistentry> | ||
381 | <term><errorcode>ENOSPC</errorcode></term> | ||
382 | <listitem> | ||
383 | <para>This is returned when either one or more of the num_entities, | ||
384 | num_interfaces, num_links or num_pads are non-zero and are smaller | ||
385 | than the actual number of elements inside the graph. This may happen | ||
386 | if the <constant>topology_version</constant> changed when compared | ||
387 | to the last time this ioctl was called. Userspace should usually | ||
388 | free the area for the pointers, zero the struct elements and call | ||
389 | this ioctl again.</para> | ||
390 | </listitem> | ||
391 | </varlistentry> | ||
392 | </variablelist> | ||
393 | </refsect1> | ||
394 | </refentry> | ||
diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml new file mode 100644 index 000000000000..1af384250910 --- /dev/null +++ b/Documentation/DocBook/media/v4l/media-types.xml | |||
@@ -0,0 +1,240 @@ | |||
1 | <section id="media-controller-types"> | ||
2 | <title>Types and flags used to represent the media graph elements</title> | ||
3 | |||
4 | <table frame="none" pgwide="1" id="media-entity-type"> | ||
5 | <title>Media entity types</title> | ||
6 | <tgroup cols="2"> | ||
7 | <colspec colname="c1"/> | ||
8 | <colspec colname="c2"/> | ||
9 | <tbody valign="top"> | ||
10 | <row> | ||
11 | <entry><constant>MEDIA_ENT_F_UNKNOWN</constant> and <constant>MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN</constant></entry> | ||
12 | <entry>Unknown entity. That generally indicates that | ||
13 | a driver didn't initialize properly the entity, with is a Kernel bug</entry> | ||
14 | </row> | ||
15 | <row> | ||
16 | <entry><constant>MEDIA_ENT_F_IO_V4L</constant></entry> | ||
17 | <entry>Data streaming input and/or output entity.</entry> | ||
18 | </row> | ||
19 | <row> | ||
20 | <entry><constant>MEDIA_ENT_F_IO_VBI</constant></entry> | ||
21 | <entry>V4L VBI streaming input or output entity</entry> | ||
22 | </row> | ||
23 | <row> | ||
24 | <entry><constant>MEDIA_ENT_F_IO_SWRADIO</constant></entry> | ||
25 | <entry>V4L Software Digital Radio (SDR) streaming input or output entity</entry> | ||
26 | </row> | ||
27 | <row> | ||
28 | <entry><constant>MEDIA_ENT_F_IO_DTV</constant></entry> | ||
29 | <entry>DVB Digital TV streaming input or output entity</entry> | ||
30 | </row> | ||
31 | <row> | ||
32 | <entry><constant>MEDIA_ENT_F_DTV_DEMOD</constant></entry> | ||
33 | <entry>Digital TV demodulator entity.</entry> | ||
34 | </row> | ||
35 | <row> | ||
36 | <entry><constant>MEDIA_ENT_F_TS_DEMUX</constant></entry> | ||
37 | <entry>MPEG Transport stream demux entity. Could be implemented on hardware or in Kernelspace by the Linux DVB subsystem.</entry> | ||
38 | </row> | ||
39 | <row> | ||
40 | <entry><constant>MEDIA_ENT_F_DTV_CA</constant></entry> | ||
41 | <entry>Digital TV Conditional Access module (CAM) entity</entry> | ||
42 | </row> | ||
43 | <row> | ||
44 | <entry><constant>MEDIA_ENT_F_DTV_NET_DECAP</constant></entry> | ||
45 | <entry>Digital TV network ULE/MLE desencapsulation entity. Could be implemented on hardware or in Kernelspace</entry> | ||
46 | </row> | ||
47 | <row> | ||
48 | <entry><constant>MEDIA_ENT_F_CONN_RF</constant></entry> | ||
49 | <entry>Connector for a Radio Frequency (RF) signal.</entry> | ||
50 | </row> | ||
51 | <row> | ||
52 | <entry><constant>MEDIA_ENT_F_CONN_SVIDEO</constant></entry> | ||
53 | <entry>Connector for a S-Video signal.</entry> | ||
54 | </row> | ||
55 | <row> | ||
56 | <entry><constant>MEDIA_ENT_F_CONN_COMPOSITE</constant></entry> | ||
57 | <entry>Connector for a RGB composite signal.</entry> | ||
58 | </row> | ||
59 | <row> | ||
60 | <entry><constant>MEDIA_ENT_F_CONN_TEST</constant></entry> | ||
61 | <entry>Connector for a test generator.</entry> | ||
62 | </row> | ||
63 | <row> | ||
64 | <entry><constant>MEDIA_ENT_F_CAM_SENSOR</constant></entry> | ||
65 | <entry>Camera video sensor entity.</entry> | ||
66 | </row> | ||
67 | <row> | ||
68 | <entry><constant>MEDIA_ENT_F_FLASH</constant></entry> | ||
69 | <entry>Flash controller entity.</entry> | ||
70 | </row> | ||
71 | <row> | ||
72 | <entry><constant>MEDIA_ENT_F_LENS</constant></entry> | ||
73 | <entry>Lens controller entity.</entry> | ||
74 | </row> | ||
75 | <row> | ||
76 | <entry><constant>MEDIA_ENT_F_ATV_DECODER</constant></entry> | ||
77 | <entry>Analog video decoder, the basic function of the video decoder | ||
78 | is to accept analogue video from a wide variety of sources such as | ||
79 | broadcast, DVD players, cameras and video cassette recorders, in | ||
80 | either NTSC, PAL, SECAM or HD format, separating the stream | ||
81 | into its component parts, luminance and chrominance, and output | ||
82 | it in some digital video standard, with appropriate timing | ||
83 | signals.</entry> | ||
84 | </row> | ||
85 | <row> | ||
86 | <entry><constant>MEDIA_ENT_F_TUNER</constant></entry> | ||
87 | <entry>Digital TV, analog TV, radio and/or software radio tuner.</entry> | ||
88 | </row> | ||
89 | </tbody> | ||
90 | </tgroup> | ||
91 | </table> | ||
92 | |||
93 | <table frame="none" pgwide="1" id="media-entity-flag"> | ||
94 | <title>Media entity flags</title> | ||
95 | <tgroup cols="2"> | ||
96 | <colspec colname="c1"/> | ||
97 | <colspec colname="c2"/> | ||
98 | <tbody valign="top"> | ||
99 | <row> | ||
100 | <entry><constant>MEDIA_ENT_FL_DEFAULT</constant></entry> | ||
101 | <entry>Default entity for its type. Used to discover the default | ||
102 | audio, VBI and video devices, the default camera sensor, ...</entry> | ||
103 | </row> | ||
104 | <row> | ||
105 | <entry><constant>MEDIA_ENT_FL_CONNECTOR</constant></entry> | ||
106 | <entry>The entity represents a data conector</entry> | ||
107 | </row> | ||
108 | </tbody> | ||
109 | </tgroup> | ||
110 | </table> | ||
111 | |||
112 | <table frame="none" pgwide="1" id="media-intf-type"> | ||
113 | <title>Media interface types</title> | ||
114 | <tgroup cols="3"> | ||
115 | <colspec colname="c1"/> | ||
116 | <colspec colname="c2"/> | ||
117 | <colspec colname="c3"/> | ||
118 | <tbody valign="top"> | ||
119 | <row> | ||
120 | <entry><constant>MEDIA_INTF_T_DVB_FE</constant></entry> | ||
121 | <entry>Device node interface for the Digital TV frontend</entry> | ||
122 | <entry>typically, /dev/dvb/adapter?/frontend?</entry> | ||
123 | </row> | ||
124 | <row> | ||
125 | <entry><constant>MEDIA_INTF_T_DVB_DEMUX</constant></entry> | ||
126 | <entry>Device node interface for the Digital TV demux</entry> | ||
127 | <entry>typically, /dev/dvb/adapter?/demux?</entry> | ||
128 | </row> | ||
129 | <row> | ||
130 | <entry><constant>MEDIA_INTF_T_DVB_DVR</constant></entry> | ||
131 | <entry>Device node interface for the Digital TV DVR</entry> | ||
132 | <entry>typically, /dev/dvb/adapter?/dvr?</entry> | ||
133 | </row> | ||
134 | <row> | ||
135 | <entry><constant>MEDIA_INTF_T_DVB_CA</constant></entry> | ||
136 | <entry>Device node interface for the Digital TV Conditional Access</entry> | ||
137 | <entry>typically, /dev/dvb/adapter?/ca?</entry> | ||
138 | </row> | ||
139 | <row> | ||
140 | <entry><constant>MEDIA_INTF_T_DVB_FE</constant></entry> | ||
141 | <entry>Device node interface for the Digital TV network control</entry> | ||
142 | <entry>typically, /dev/dvb/adapter?/net?</entry> | ||
143 | </row> | ||
144 | <row> | ||
145 | <entry><constant>MEDIA_INTF_T_V4L_VIDEO</constant></entry> | ||
146 | <entry>Device node interface for video (V4L)</entry> | ||
147 | <entry>typically, /dev/video?</entry> | ||
148 | </row> | ||
149 | <row> | ||
150 | <entry><constant>MEDIA_INTF_T_V4L_VBI</constant></entry> | ||
151 | <entry>Device node interface for VBI (V4L)</entry> | ||
152 | <entry>typically, /dev/vbi?</entry> | ||
153 | </row> | ||
154 | <row> | ||
155 | <entry><constant>MEDIA_INTF_T_V4L_RADIO</constant></entry> | ||
156 | <entry>Device node interface for radio (V4L)</entry> | ||
157 | <entry>typically, /dev/vbi?</entry> | ||
158 | </row> | ||
159 | <row> | ||
160 | <entry><constant>MEDIA_INTF_T_V4L_SUBDEV</constant></entry> | ||
161 | <entry>Device node interface for a V4L subdevice</entry> | ||
162 | <entry>typically, /dev/v4l-subdev?</entry> | ||
163 | </row> | ||
164 | <row> | ||
165 | <entry><constant>MEDIA_INTF_T_V4L_SWRADIO</constant></entry> | ||
166 | <entry>Device node interface for Software Defined Radio (V4L)</entry> | ||
167 | <entry>typically, /dev/swradio?</entry> | ||
168 | </row> | ||
169 | </tbody> | ||
170 | </tgroup> | ||
171 | </table> | ||
172 | |||
173 | <table frame="none" pgwide="1" id="media-pad-flag"> | ||
174 | <title>Media pad flags</title> | ||
175 | <tgroup cols="2"> | ||
176 | <colspec colname="c1"/> | ||
177 | <colspec colname="c2"/> | ||
178 | <tbody valign="top"> | ||
179 | <row> | ||
180 | <entry><constant>MEDIA_PAD_FL_SINK</constant></entry> | ||
181 | <entry>Input pad, relative to the entity. Input pads sink data and | ||
182 | are targets of links.</entry> | ||
183 | </row> | ||
184 | <row> | ||
185 | <entry><constant>MEDIA_PAD_FL_SOURCE</constant></entry> | ||
186 | <entry>Output pad, relative to the entity. Output pads source data | ||
187 | and are origins of links.</entry> | ||
188 | </row> | ||
189 | <row> | ||
190 | <entry><constant>MEDIA_PAD_FL_MUST_CONNECT</constant></entry> | ||
191 | <entry>If this flag is set and the pad is linked to any other | ||
192 | pad, then at least one of those links must be enabled for the | ||
193 | entity to be able to stream. There could be temporary reasons | ||
194 | (e.g. device configuration dependent) for the pad to need | ||
195 | enabled links even when this flag isn't set; the absence of the | ||
196 | flag doesn't imply there is none.</entry> | ||
197 | </row> | ||
198 | </tbody> | ||
199 | </tgroup> | ||
200 | </table> | ||
201 | |||
202 | <para>One and only one of <constant>MEDIA_PAD_FL_SINK</constant> and | ||
203 | <constant>MEDIA_PAD_FL_SOURCE</constant> must be set for every pad.</para> | ||
204 | |||
205 | <table frame="none" pgwide="1" id="media-link-flag"> | ||
206 | <title>Media link flags</title> | ||
207 | <tgroup cols="2"> | ||
208 | <colspec colname="c1"/> | ||
209 | <colspec colname="c2"/> | ||
210 | <tbody valign="top"> | ||
211 | <row> | ||
212 | <entry><constant>MEDIA_LNK_FL_ENABLED</constant></entry> | ||
213 | <entry>The link is enabled and can be used to transfer media data. | ||
214 | When two or more links target a sink pad, only one of them can be | ||
215 | enabled at a time.</entry> | ||
216 | </row> | ||
217 | <row> | ||
218 | <entry><constant>MEDIA_LNK_FL_IMMUTABLE</constant></entry> | ||
219 | <entry>The link enabled state can't be modified at runtime. An | ||
220 | immutable link is always enabled.</entry> | ||
221 | </row> | ||
222 | <row> | ||
223 | <entry><constant>MEDIA_LNK_FL_DYNAMIC</constant></entry> | ||
224 | <entry>The link enabled state can be modified during streaming. This | ||
225 | flag is set by drivers and is read-only for applications.</entry> | ||
226 | </row> | ||
227 | <row> | ||
228 | <entry><constant>MEDIA_LNK_FL_LINK_TYPE</constant></entry> | ||
229 | <entry><para>This is a bitmask that defines the type of the link. | ||
230 | Currently, two types of links are supported:</para> | ||
231 | <para><constant>MEDIA_LNK_FL_DATA_LINK</constant> | ||
232 | if the link is between two pads</para> | ||
233 | <para><constant>MEDIA_LNK_FL_INTERFACE_LINK</constant> | ||
234 | if the link is between an interface and an entity</para></entry> | ||
235 | </row> | ||
236 | </tbody> | ||
237 | </tgroup> | ||
238 | </table> | ||
239 | |||
240 | </section> | ||
diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt deleted file mode 100644 index f552a75c0e70..000000000000 --- a/Documentation/media-framework.txt +++ /dev/null | |||
@@ -1,372 +0,0 @@ | |||
1 | Linux kernel media framework | ||
2 | ============================ | ||
3 | |||
4 | This document describes the Linux kernel media framework, its data structures, | ||
5 | functions and their usage. | ||
6 | |||
7 | |||
8 | Introduction | ||
9 | ------------ | ||
10 | |||
11 | The media controller API is documented in DocBook format in | ||
12 | Documentation/DocBook/media/v4l/media-controller.xml. This document will focus | ||
13 | on the kernel-side implementation of the media framework. | ||
14 | |||
15 | |||
16 | Abstract media device model | ||
17 | --------------------------- | ||
18 | |||
19 | Discovering a device internal topology, and configuring it at runtime, is one | ||
20 | of the goals of the media framework. To achieve this, hardware devices are | ||
21 | modelled as an oriented graph of building blocks called entities connected | ||
22 | through pads. | ||
23 | |||
24 | An entity is a basic media hardware building block. It can correspond to | ||
25 | a large variety of logical blocks such as physical hardware devices | ||
26 | (CMOS sensor for instance), logical hardware devices (a building block | ||
27 | in a System-on-Chip image processing pipeline), DMA channels or physical | ||
28 | connectors. | ||
29 | |||
30 | A pad is a connection endpoint through which an entity can interact with | ||
31 | other entities. Data (not restricted to video) produced by an entity | ||
32 | flows from the entity's output to one or more entity inputs. Pads should | ||
33 | not be confused with physical pins at chip boundaries. | ||
34 | |||
35 | A link is a point-to-point oriented connection between two pads, either | ||
36 | on the same entity or on different entities. Data flows from a source | ||
37 | pad to a sink pad. | ||
38 | |||
39 | |||
40 | Media device | ||
41 | ------------ | ||
42 | |||
43 | A media device is represented by a struct media_device instance, defined in | ||
44 | include/media/media-device.h. Allocation of the structure is handled by the | ||
45 | media device driver, usually by embedding the media_device instance in a | ||
46 | larger driver-specific structure. | ||
47 | |||
48 | Drivers register media device instances by calling | ||
49 | |||
50 | media_device_register(struct media_device *mdev); | ||
51 | |||
52 | The caller is responsible for initializing the media_device structure before | ||
53 | registration. The following fields must be set: | ||
54 | |||
55 | - dev must point to the parent device (usually a pci_dev, usb_interface or | ||
56 | platform_device instance). | ||
57 | |||
58 | - model must be filled with the device model name as a NUL-terminated UTF-8 | ||
59 | string. The device/model revision must not be stored in this field. | ||
60 | |||
61 | The following fields are optional: | ||
62 | |||
63 | - serial is a unique serial number stored as a NUL-terminated ASCII string. | ||
64 | The field is big enough to store a GUID in text form. If the hardware | ||
65 | doesn't provide a unique serial number this field must be left empty. | ||
66 | |||
67 | - bus_info represents the location of the device in the system as a | ||
68 | NUL-terminated ASCII string. For PCI/PCIe devices bus_info must be set to | ||
69 | "PCI:" (or "PCIe:") followed by the value of pci_name(). For USB devices, | ||
70 | the usb_make_path() function must be used. This field is used by | ||
71 | applications to distinguish between otherwise identical devices that don't | ||
72 | provide a serial number. | ||
73 | |||
74 | - hw_revision is the hardware device revision in a driver-specific format. | ||
75 | When possible the revision should be formatted with the KERNEL_VERSION | ||
76 | macro. | ||
77 | |||
78 | - driver_version is formatted with the KERNEL_VERSION macro. The version | ||
79 | minor must be incremented when new features are added to the userspace API | ||
80 | without breaking binary compatibility. The version major must be | ||
81 | incremented when binary compatibility is broken. | ||
82 | |||
83 | Upon successful registration a character device named media[0-9]+ is created. | ||
84 | The device major and minor numbers are dynamic. The model name is exported as | ||
85 | a sysfs attribute. | ||
86 | |||
87 | Drivers unregister media device instances by calling | ||
88 | |||
89 | media_device_unregister(struct media_device *mdev); | ||
90 | |||
91 | Unregistering a media device that hasn't been registered is *NOT* safe. | ||
92 | |||
93 | |||
94 | Entities, pads and links | ||
95 | ------------------------ | ||
96 | |||
97 | - Entities | ||
98 | |||
99 | Entities are represented by a struct media_entity instance, defined in | ||
100 | include/media/media-entity.h. The structure is usually embedded into a | ||
101 | higher-level structure, such as a v4l2_subdev or video_device instance, | ||
102 | although drivers can allocate entities directly. | ||
103 | |||
104 | Drivers initialize entities by calling | ||
105 | |||
106 | media_entity_init(struct media_entity *entity, u16 num_pads, | ||
107 | struct media_pad *pads, u16 extra_links); | ||
108 | |||
109 | The media_entity name, type, flags, revision and group_id fields can be | ||
110 | initialized before or after calling media_entity_init. Entities embedded in | ||
111 | higher-level standard structures can have some of those fields set by the | ||
112 | higher-level framework. | ||
113 | |||
114 | As the number of pads is known in advance, the pads array is not allocated | ||
115 | dynamically but is managed by the entity driver. Most drivers will embed the | ||
116 | pads array in a driver-specific structure, avoiding dynamic allocation. | ||
117 | |||
118 | Drivers must set the direction of every pad in the pads array before calling | ||
119 | media_entity_init. The function will initialize the other pads fields. | ||
120 | |||
121 | Unlike the number of pads, the total number of links isn't always known in | ||
122 | advance by the entity driver. As an initial estimate, media_entity_init | ||
123 | pre-allocates a number of links equal to the number of pads plus an optional | ||
124 | number of extra links. The links array will be reallocated if it grows beyond | ||
125 | the initial estimate. | ||
126 | |||
127 | Drivers register entities with a media device by calling | ||
128 | |||
129 | media_device_register_entity(struct media_device *mdev, | ||
130 | struct media_entity *entity); | ||
131 | |||
132 | Entities are identified by a unique positive integer ID. Drivers can provide an | ||
133 | ID by filling the media_entity id field prior to registration, or request the | ||
134 | media controller framework to assign an ID automatically. Drivers that provide | ||
135 | IDs manually must ensure that all IDs are unique. IDs are not guaranteed to be | ||
136 | contiguous even when they are all assigned automatically by the framework. | ||
137 | |||
138 | Drivers unregister entities by calling | ||
139 | |||
140 | media_device_unregister_entity(struct media_entity *entity); | ||
141 | |||
142 | Unregistering an entity will not change the IDs of the other entities, and the | ||
143 | ID will never be reused for a newly registered entity. | ||
144 | |||
145 | When a media device is unregistered, all its entities are unregistered | ||
146 | automatically. No manual entities unregistration is then required. | ||
147 | |||
148 | Drivers free resources associated with an entity by calling | ||
149 | |||
150 | media_entity_cleanup(struct media_entity *entity); | ||
151 | |||
152 | This function must be called during the cleanup phase after unregistering the | ||
153 | entity. Note that the media_entity instance itself must be freed explicitly by | ||
154 | the driver if required. | ||
155 | |||
156 | Entities have flags that describe the entity capabilities and state. | ||
157 | |||
158 | MEDIA_ENT_FL_DEFAULT indicates the default entity for a given type. | ||
159 | This can be used to report the default audio and video devices or the | ||
160 | default camera sensor. | ||
161 | |||
162 | Logical entity groups can be defined by setting the group ID of all member | ||
163 | entities to the same non-zero value. An entity group serves no purpose in the | ||
164 | kernel, but is reported to userspace during entities enumeration. The group_id | ||
165 | field belongs to the media device driver and must not by touched by entity | ||
166 | drivers. | ||
167 | |||
168 | Media device drivers should define groups if several entities are logically | ||
169 | bound together. Example usages include reporting | ||
170 | |||
171 | - ALSA, VBI and video nodes that carry the same media stream | ||
172 | - lens and flash controllers associated with a sensor | ||
173 | |||
174 | - Pads | ||
175 | |||
176 | Pads are represented by a struct media_pad instance, defined in | ||
177 | include/media/media-entity.h. Each entity stores its pads in a pads array | ||
178 | managed by the entity driver. Drivers usually embed the array in a | ||
179 | driver-specific structure. | ||
180 | |||
181 | Pads are identified by their entity and their 0-based index in the pads array. | ||
182 | Both information are stored in the media_pad structure, making the media_pad | ||
183 | pointer the canonical way to store and pass link references. | ||
184 | |||
185 | Pads have flags that describe the pad capabilities and state. | ||
186 | |||
187 | MEDIA_PAD_FL_SINK indicates that the pad supports sinking data. | ||
188 | MEDIA_PAD_FL_SOURCE indicates that the pad supports sourcing data. | ||
189 | |||
190 | One and only one of MEDIA_PAD_FL_SINK and MEDIA_PAD_FL_SOURCE must be set for | ||
191 | each pad. | ||
192 | |||
193 | - Links | ||
194 | |||
195 | Links are represented by a struct media_link instance, defined in | ||
196 | include/media/media-entity.h. Each entity stores all links originating at or | ||
197 | targeting any of its pads in a links array. A given link is thus stored | ||
198 | twice, once in the source entity and once in the target entity. The array is | ||
199 | pre-allocated and grows dynamically as needed. | ||
200 | |||
201 | Drivers create links by calling | ||
202 | |||
203 | media_entity_create_link(struct media_entity *source, u16 source_pad, | ||
204 | struct media_entity *sink, u16 sink_pad, | ||
205 | u32 flags); | ||
206 | |||
207 | An entry in the link array of each entity is allocated and stores pointers | ||
208 | to source and sink pads. | ||
209 | |||
210 | Links have flags that describe the link capabilities and state. | ||
211 | |||
212 | MEDIA_LNK_FL_ENABLED indicates that the link is enabled and can be used | ||
213 | to transfer media data. When two or more links target a sink pad, only | ||
214 | one of them can be enabled at a time. | ||
215 | MEDIA_LNK_FL_IMMUTABLE indicates that the link enabled state can't be | ||
216 | modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then | ||
217 | MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always | ||
218 | enabled. | ||
219 | |||
220 | |||
221 | Graph traversal | ||
222 | --------------- | ||
223 | |||
224 | The media framework provides APIs to iterate over entities in a graph. | ||
225 | |||
226 | To iterate over all entities belonging to a media device, drivers can use the | ||
227 | media_device_for_each_entity macro, defined in include/media/media-device.h. | ||
228 | |||
229 | struct media_entity *entity; | ||
230 | |||
231 | media_device_for_each_entity(entity, mdev) { | ||
232 | /* entity will point to each entity in turn */ | ||
233 | ... | ||
234 | } | ||
235 | |||
236 | Drivers might also need to iterate over all entities in a graph that can be | ||
237 | reached only through enabled links starting at a given entity. The media | ||
238 | framework provides a depth-first graph traversal API for that purpose. | ||
239 | |||
240 | Note that graphs with cycles (whether directed or undirected) are *NOT* | ||
241 | supported by the graph traversal API. To prevent infinite loops, the graph | ||
242 | traversal code limits the maximum depth to MEDIA_ENTITY_ENUM_MAX_DEPTH, | ||
243 | currently defined as 16. | ||
244 | |||
245 | Drivers initiate a graph traversal by calling | ||
246 | |||
247 | media_entity_graph_walk_start(struct media_entity_graph *graph, | ||
248 | struct media_entity *entity); | ||
249 | |||
250 | The graph structure, provided by the caller, is initialized to start graph | ||
251 | traversal at the given entity. | ||
252 | |||
253 | Drivers can then retrieve the next entity by calling | ||
254 | |||
255 | media_entity_graph_walk_next(struct media_entity_graph *graph); | ||
256 | |||
257 | When the graph traversal is complete the function will return NULL. | ||
258 | |||
259 | Graph traversal can be interrupted at any moment. No cleanup function call is | ||
260 | required and the graph structure can be freed normally. | ||
261 | |||
262 | Helper functions can be used to find a link between two given pads, or a pad | ||
263 | connected to another pad through an enabled link | ||
264 | |||
265 | media_entity_find_link(struct media_pad *source, | ||
266 | struct media_pad *sink); | ||
267 | |||
268 | media_entity_remote_pad(struct media_pad *pad); | ||
269 | |||
270 | Refer to the kerneldoc documentation for more information. | ||
271 | |||
272 | |||
273 | Use count and power handling | ||
274 | ---------------------------- | ||
275 | |||
276 | Due to the wide differences between drivers regarding power management needs, | ||
277 | the media controller does not implement power management. However, the | ||
278 | media_entity structure includes a use_count field that media drivers can use to | ||
279 | track the number of users of every entity for power management needs. | ||
280 | |||
281 | The use_count field is owned by media drivers and must not be touched by entity | ||
282 | drivers. Access to the field must be protected by the media device graph_mutex | ||
283 | lock. | ||
284 | |||
285 | |||
286 | Links setup | ||
287 | ----------- | ||
288 | |||
289 | Link properties can be modified at runtime by calling | ||
290 | |||
291 | media_entity_setup_link(struct media_link *link, u32 flags); | ||
292 | |||
293 | The flags argument contains the requested new link flags. | ||
294 | |||
295 | The only configurable property is the ENABLED link flag to enable/disable a | ||
296 | link. Links marked with the IMMUTABLE link flag can not be enabled or disabled. | ||
297 | |||
298 | When a link is enabled or disabled, the media framework calls the | ||
299 | link_setup operation for the two entities at the source and sink of the link, | ||
300 | in that order. If the second link_setup call fails, another link_setup call is | ||
301 | made on the first entity to restore the original link flags. | ||
302 | |||
303 | Media device drivers can be notified of link setup operations by setting the | ||
304 | media_device::link_notify pointer to a callback function. If provided, the | ||
305 | notification callback will be called before enabling and after disabling | ||
306 | links. | ||
307 | |||
308 | Entity drivers must implement the link_setup operation if any of their links | ||
309 | is non-immutable. The operation must either configure the hardware or store | ||
310 | the configuration information to be applied later. | ||
311 | |||
312 | Link configuration must not have any side effect on other links. If an enabled | ||
313 | link at a sink pad prevents another link at the same pad from being enabled, | ||
314 | the link_setup operation must return -EBUSY and can't implicitly disable the | ||
315 | first enabled link. | ||
316 | |||
317 | |||
318 | Pipelines and media streams | ||
319 | --------------------------- | ||
320 | |||
321 | When starting streaming, drivers must notify all entities in the pipeline to | ||
322 | prevent link states from being modified during streaming by calling | ||
323 | |||
324 | media_entity_pipeline_start(struct media_entity *entity, | ||
325 | struct media_pipeline *pipe); | ||
326 | |||
327 | The function will mark all entities connected to the given entity through | ||
328 | enabled links, either directly or indirectly, as streaming. | ||
329 | |||
330 | The media_pipeline instance pointed to by the pipe argument will be stored in | ||
331 | every entity in the pipeline. Drivers should embed the media_pipeline structure | ||
332 | in higher-level pipeline structures and can then access the pipeline through | ||
333 | the media_entity pipe field. | ||
334 | |||
335 | Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must | ||
336 | be identical for all nested calls to the function. | ||
337 | |||
338 | media_entity_pipeline_start() may return an error. In that case, it will | ||
339 | clean up any of the changes it did by itself. | ||
340 | |||
341 | When stopping the stream, drivers must notify the entities with | ||
342 | |||
343 | media_entity_pipeline_stop(struct media_entity *entity); | ||
344 | |||
345 | If multiple calls to media_entity_pipeline_start() have been made the same | ||
346 | number of media_entity_pipeline_stop() calls are required to stop streaming. The | ||
347 | media_entity pipe field is reset to NULL on the last nested stop call. | ||
348 | |||
349 | Link configuration will fail with -EBUSY by default if either end of the link is | ||
350 | a streaming entity. Links that can be modified while streaming must be marked | ||
351 | with the MEDIA_LNK_FL_DYNAMIC flag. | ||
352 | |||
353 | If other operations need to be disallowed on streaming entities (such as | ||
354 | changing entities configuration parameters) drivers can explicitly check the | ||
355 | media_entity stream_count field to find out if an entity is streaming. This | ||
356 | operation must be done with the media_device graph_mutex held. | ||
357 | |||
358 | |||
359 | Link validation | ||
360 | --------------- | ||
361 | |||
362 | Link validation is performed by media_entity_pipeline_start() for any | ||
363 | entity which has sink pads in the pipeline. The | ||
364 | media_entity::link_validate() callback is used for that purpose. In | ||
365 | link_validate() callback, entity driver should check that the properties of | ||
366 | the source pad of the connected entity and its own sink pad match. It is up | ||
367 | to the type of the entity (and in the end, the properties of the hardware) | ||
368 | what matching actually means. | ||
369 | |||
370 | Subsystems should facilitate link validation by providing subsystem specific | ||
371 | helper functions to provide easy access for commonly needed information, and | ||
372 | in the end provide a way to use driver-specific callbacks. | ||
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 75d5c18d689a..fa41608ab2b4 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt | |||
@@ -295,16 +295,16 @@ module owner. This is done for you if you use the i2c helper functions. | |||
295 | 295 | ||
296 | If integration with the media framework is needed, you must initialize the | 296 | If integration with the media framework is needed, you must initialize the |
297 | media_entity struct embedded in the v4l2_subdev struct (entity field) by | 297 | media_entity struct embedded in the v4l2_subdev struct (entity field) by |
298 | calling media_entity_init(): | 298 | calling media_entity_pads_init(), if the entity has pads: |
299 | 299 | ||
300 | struct media_pad *pads = &my_sd->pads; | 300 | struct media_pad *pads = &my_sd->pads; |
301 | int err; | 301 | int err; |
302 | 302 | ||
303 | err = media_entity_init(&sd->entity, npads, pads, 0); | 303 | err = media_entity_pads_init(&sd->entity, npads, pads); |
304 | 304 | ||
305 | The pads array must have been previously initialized. There is no need to | 305 | The pads array must have been previously initialized. There is no need to |
306 | manually set the struct media_entity type and name fields, but the revision | 306 | manually set the struct media_entity function and name fields, but the |
307 | field must be initialized if needed. | 307 | revision field must be initialized if needed. |
308 | 308 | ||
309 | A reference to the entity will be automatically acquired/released when the | 309 | A reference to the entity will be automatically acquired/released when the |
310 | subdev device node (if any) is opened/closed. | 310 | subdev device node (if any) is opened/closed. |
@@ -695,12 +695,12 @@ difference is that the inode argument is omitted since it is never used. | |||
695 | 695 | ||
696 | If integration with the media framework is needed, you must initialize the | 696 | If integration with the media framework is needed, you must initialize the |
697 | media_entity struct embedded in the video_device struct (entity field) by | 697 | media_entity struct embedded in the video_device struct (entity field) by |
698 | calling media_entity_init(): | 698 | calling media_entity_pads_init(): |
699 | 699 | ||
700 | struct media_pad *pad = &my_vdev->pad; | 700 | struct media_pad *pad = &my_vdev->pad; |
701 | int err; | 701 | int err; |
702 | 702 | ||
703 | err = media_entity_init(&vdev->entity, 1, pad, 0); | 703 | err = media_entity_pads_init(&vdev->entity, 1, pad); |
704 | 704 | ||
705 | The pads array must have been previously initialized. There is no need to | 705 | The pads array must have been previously initialized. There is no need to |
706 | manually set the struct media_entity type and name fields. | 706 | manually set the struct media_entity type and name fields. |
diff --git a/Documentation/zh_CN/video4linux/v4l2-framework.txt b/Documentation/zh_CN/video4linux/v4l2-framework.txt index 2b828e631e31..698660b7f21f 100644 --- a/Documentation/zh_CN/video4linux/v4l2-framework.txt +++ b/Documentation/zh_CN/video4linux/v4l2-framework.txt | |||
@@ -289,13 +289,13 @@ struct v4l2_subdev_ops { | |||
289 | 然后,你必须用一个唯一的名字初始化 subdev->name,并初始化模块的 | 289 | 然后,你必须用一个唯一的名字初始化 subdev->name,并初始化模块的 |
290 | owner 域。若使用 i2c 辅助函数,这些都会帮你处理好。 | 290 | owner 域。若使用 i2c 辅助函数,这些都会帮你处理好。 |
291 | 291 | ||
292 | 若需同媒体框架整合,你必须调用 media_entity_init() 初始化 v4l2_subdev | 292 | 若需同媒体框架整合,你必须调用 media_entity_pads_init() 初始化 v4l2_subdev |
293 | 结构体中的 media_entity 结构体(entity 域): | 293 | 结构体中的 media_entity 结构体(entity 域): |
294 | 294 | ||
295 | struct media_pad *pads = &my_sd->pads; | 295 | struct media_pad *pads = &my_sd->pads; |
296 | int err; | 296 | int err; |
297 | 297 | ||
298 | err = media_entity_init(&sd->entity, npads, pads, 0); | 298 | err = media_entity_pads_init(&sd->entity, npads, pads); |
299 | 299 | ||
300 | pads 数组必须预先初始化。无须手动设置 media_entity 的 type 和 | 300 | pads 数组必须预先初始化。无须手动设置 media_entity 的 type 和 |
301 | name 域,但如有必要,revision 域必须初始化。 | 301 | name 域,但如有必要,revision 域必须初始化。 |
@@ -596,13 +596,13 @@ void v4l2_disable_ioctl(struct video_device *vdev, unsigned int cmd); | |||
596 | v4l2_file_operations 结构体是 file_operations 的一个子集。其主要 | 596 | v4l2_file_operations 结构体是 file_operations 的一个子集。其主要 |
597 | 区别在于:因 inode 参数从未被使用,它将被忽略。 | 597 | 区别在于:因 inode 参数从未被使用,它将被忽略。 |
598 | 598 | ||
599 | 如果需要与媒体框架整合,你必须通过调用 media_entity_init() 初始化 | 599 | 如果需要与媒体框架整合,你必须通过调用 media_entity_pads_init() 初始化 |
600 | 嵌入在 video_device 结构体中的 media_entity(entity 域)结构体: | 600 | 嵌入在 video_device 结构体中的 media_entity(entity 域)结构体: |
601 | 601 | ||
602 | struct media_pad *pad = &my_vdev->pad; | 602 | struct media_pad *pad = &my_vdev->pad; |
603 | int err; | 603 | int err; |
604 | 604 | ||
605 | err = media_entity_init(&vdev->entity, 1, pad, 0); | 605 | err = media_entity_pads_init(&vdev->entity, 1, pad); |
606 | 606 | ||
607 | pads 数组必须预先初始化。没有必要手动设置 media_entity 的 type 和 | 607 | pads 数组必须预先初始化。没有必要手动设置 media_entity 的 type 和 |
608 | name 域。 | 608 | name 域。 |
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 9264ea73b3be..a8518fb3bca7 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig | |||
@@ -97,7 +97,6 @@ config MEDIA_CONTROLLER | |||
97 | config MEDIA_CONTROLLER_DVB | 97 | config MEDIA_CONTROLLER_DVB |
98 | bool "Enable Media controller for DVB (EXPERIMENTAL)" | 98 | bool "Enable Media controller for DVB (EXPERIMENTAL)" |
99 | depends on MEDIA_CONTROLLER | 99 | depends on MEDIA_CONTROLLER |
100 | depends on BROKEN | ||
101 | ---help--- | 100 | ---help--- |
102 | Enable the media controller API support for DVB. | 101 | Enable the media controller API support for DVB. |
103 | 102 | ||
diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index f4305ae800f4..d31f468830cf 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c | |||
@@ -617,6 +617,7 @@ static void smsdvb_media_device_unregister(struct smsdvb_client_t *client) | |||
617 | if (!coredev->media_dev) | 617 | if (!coredev->media_dev) |
618 | return; | 618 | return; |
619 | media_device_unregister(coredev->media_dev); | 619 | media_device_unregister(coredev->media_dev); |
620 | media_device_cleanup(coredev->media_dev); | ||
620 | kfree(coredev->media_dev); | 621 | kfree(coredev->media_dev); |
621 | coredev->media_dev = NULL; | 622 | coredev->media_dev = NULL; |
622 | #endif | 623 | #endif |
@@ -1183,7 +1184,11 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, | |||
1183 | if (smsdvb_debugfs_create(client) < 0) | 1184 | if (smsdvb_debugfs_create(client) < 0) |
1184 | pr_info("failed to create debugfs node\n"); | 1185 | pr_info("failed to create debugfs node\n"); |
1185 | 1186 | ||
1186 | dvb_create_media_graph(&client->adapter); | 1187 | rc = dvb_create_media_graph(&client->adapter, true); |
1188 | if (rc < 0) { | ||
1189 | pr_err("dvb_create_media_graph failed %d\n", rc); | ||
1190 | goto client_error; | ||
1191 | } | ||
1187 | 1192 | ||
1188 | pr_info("DVB interface registered.\n"); | 1193 | pr_info("DVB interface registered.\n"); |
1189 | return 0; | 1194 | return 0; |
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index ea9abde902e9..a168cbe1c998 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c | |||
@@ -1244,9 +1244,9 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) | |||
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, | 1246 | dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, |
1247 | DVB_DEVICE_DEMUX); | 1247 | DVB_DEVICE_DEMUX, dmxdev->filternum); |
1248 | dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, | 1248 | dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, |
1249 | dmxdev, DVB_DEVICE_DVR); | 1249 | dmxdev, DVB_DEVICE_DVR, dmxdev->filternum); |
1250 | 1250 | ||
1251 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); | 1251 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); |
1252 | 1252 | ||
diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index fb66184dc9b6..f82cd1ff4f3a 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c | |||
@@ -1695,7 +1695,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, | |||
1695 | pubca->private = ca; | 1695 | pubca->private = ca; |
1696 | 1696 | ||
1697 | /* register the DVB device */ | 1697 | /* register the DVB device */ |
1698 | ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA); | 1698 | ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA, 0); |
1699 | if (ret) | 1699 | if (ret) |
1700 | goto free_slot_info; | 1700 | goto free_slot_info; |
1701 | 1701 | ||
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index b64f33776b74..40080645341e 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c | |||
@@ -622,7 +622,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe) | |||
622 | struct media_device *mdev = adapter->mdev; | 622 | struct media_device *mdev = adapter->mdev; |
623 | struct media_entity *entity, *source; | 623 | struct media_entity *entity, *source; |
624 | struct media_link *link, *found_link = NULL; | 624 | struct media_link *link, *found_link = NULL; |
625 | int i, ret, n_links = 0, active_links = 0; | 625 | int ret, n_links = 0, active_links = 0; |
626 | 626 | ||
627 | fepriv->pipe_start_entity = NULL; | 627 | fepriv->pipe_start_entity = NULL; |
628 | 628 | ||
@@ -632,8 +632,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe) | |||
632 | entity = fepriv->dvbdev->entity; | 632 | entity = fepriv->dvbdev->entity; |
633 | fepriv->pipe_start_entity = entity; | 633 | fepriv->pipe_start_entity = entity; |
634 | 634 | ||
635 | for (i = 0; i < entity->num_links; i++) { | 635 | list_for_each_entry(link, &entity->links, list) { |
636 | link = &entity->links[i]; | ||
637 | if (link->sink->entity == entity) { | 636 | if (link->sink->entity == entity) { |
638 | found_link = link; | 637 | found_link = link; |
639 | n_links++; | 638 | n_links++; |
@@ -659,13 +658,11 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe) | |||
659 | 658 | ||
660 | source = found_link->source->entity; | 659 | source = found_link->source->entity; |
661 | fepriv->pipe_start_entity = source; | 660 | fepriv->pipe_start_entity = source; |
662 | for (i = 0; i < source->num_links; i++) { | 661 | list_for_each_entry(link, &source->links, list) { |
663 | struct media_entity *sink; | 662 | struct media_entity *sink; |
664 | int flags = 0; | 663 | int flags = 0; |
665 | 664 | ||
666 | link = &source->links[i]; | ||
667 | sink = link->sink->entity; | 665 | sink = link->sink->entity; |
668 | |||
669 | if (sink == entity) | 666 | if (sink == entity) |
670 | flags = MEDIA_LNK_FL_ENABLED; | 667 | flags = MEDIA_LNK_FL_ENABLED; |
671 | 668 | ||
@@ -2762,7 +2759,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb, | |||
2762 | fe->dvb->num, fe->id, fe->ops.info.name); | 2759 | fe->dvb->num, fe->id, fe->ops.info.name); |
2763 | 2760 | ||
2764 | dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, | 2761 | dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, |
2765 | fe, DVB_DEVICE_FRONTEND); | 2762 | fe, DVB_DEVICE_FRONTEND, 0); |
2766 | 2763 | ||
2767 | /* | 2764 | /* |
2768 | * Initialize the cache to the proper values according with the | 2765 | * Initialize the cache to the proper values according with the |
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index ce4332e80a91..ce6a711b42d4 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c | |||
@@ -1502,6 +1502,6 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, | |||
1502 | dvbnet->state[i] = 0; | 1502 | dvbnet->state[i] = 0; |
1503 | 1503 | ||
1504 | return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net, | 1504 | return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net, |
1505 | dvbnet, DVB_DEVICE_NET); | 1505 | dvbnet, DVB_DEVICE_NET, 0); |
1506 | } | 1506 | } |
1507 | EXPORT_SYMBOL(dvb_net_init); | 1507 | EXPORT_SYMBOL(dvb_net_init); |
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 13bb57f0457f..560450a0b32a 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c | |||
@@ -34,6 +34,9 @@ | |||
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | #include "dvbdev.h" | 35 | #include "dvbdev.h" |
36 | 36 | ||
37 | /* Due to enum tuner_pad_index */ | ||
38 | #include <media/tuner.h> | ||
39 | |||
37 | static DEFINE_MUTEX(dvbdev_mutex); | 40 | static DEFINE_MUTEX(dvbdev_mutex); |
38 | static int dvbdev_debug; | 41 | static int dvbdev_debug; |
39 | 42 | ||
@@ -180,102 +183,255 @@ skip: | |||
180 | return -ENFILE; | 183 | return -ENFILE; |
181 | } | 184 | } |
182 | 185 | ||
183 | static void dvb_register_media_device(struct dvb_device *dvbdev, | 186 | static void dvb_media_device_free(struct dvb_device *dvbdev) |
184 | int type, int minor) | ||
185 | { | 187 | { |
186 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) | 188 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) |
187 | int ret = 0, npads; | 189 | if (dvbdev->entity) { |
190 | media_device_unregister_entity(dvbdev->entity); | ||
191 | kfree(dvbdev->entity); | ||
192 | kfree(dvbdev->pads); | ||
193 | dvbdev->entity = NULL; | ||
194 | dvbdev->pads = NULL; | ||
195 | } | ||
188 | 196 | ||
189 | if (!dvbdev->adapter->mdev) | 197 | if (dvbdev->tsout_entity) { |
190 | return; | 198 | int i; |
191 | 199 | ||
192 | dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL); | 200 | for (i = 0; i < dvbdev->tsout_num_entities; i++) { |
193 | if (!dvbdev->entity) | 201 | media_device_unregister_entity(&dvbdev->tsout_entity[i]); |
194 | return; | 202 | kfree(dvbdev->tsout_entity[i].name); |
203 | } | ||
204 | kfree(dvbdev->tsout_entity); | ||
205 | kfree(dvbdev->tsout_pads); | ||
206 | dvbdev->tsout_entity = NULL; | ||
207 | dvbdev->tsout_pads = NULL; | ||
195 | 208 | ||
196 | dvbdev->entity->info.dev.major = DVB_MAJOR; | 209 | dvbdev->tsout_num_entities = 0; |
197 | dvbdev->entity->info.dev.minor = minor; | 210 | } |
198 | dvbdev->entity->name = dvbdev->name; | 211 | |
212 | if (dvbdev->intf_devnode) { | ||
213 | media_devnode_remove(dvbdev->intf_devnode); | ||
214 | dvbdev->intf_devnode = NULL; | ||
215 | } | ||
216 | |||
217 | if (dvbdev->adapter->conn) { | ||
218 | media_device_unregister_entity(dvbdev->adapter->conn); | ||
219 | dvbdev->adapter->conn = NULL; | ||
220 | kfree(dvbdev->adapter->conn_pads); | ||
221 | dvbdev->adapter->conn_pads = NULL; | ||
222 | } | ||
223 | #endif | ||
224 | } | ||
225 | |||
226 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) | ||
227 | static int dvb_create_tsout_entity(struct dvb_device *dvbdev, | ||
228 | const char *name, int npads) | ||
229 | { | ||
230 | int i, ret = 0; | ||
231 | |||
232 | dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads), | ||
233 | GFP_KERNEL); | ||
234 | if (!dvbdev->tsout_pads) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | dvbdev->tsout_entity = kcalloc(npads, sizeof(*dvbdev->tsout_entity), | ||
238 | GFP_KERNEL); | ||
239 | if (!dvbdev->tsout_entity) | ||
240 | return -ENOMEM; | ||
241 | |||
242 | dvbdev->tsout_num_entities = npads; | ||
243 | |||
244 | for (i = 0; i < npads; i++) { | ||
245 | struct media_pad *pads = &dvbdev->tsout_pads[i]; | ||
246 | struct media_entity *entity = &dvbdev->tsout_entity[i]; | ||
247 | |||
248 | entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i); | ||
249 | if (!entity->name) | ||
250 | return -ENOMEM; | ||
251 | |||
252 | entity->function = MEDIA_ENT_F_IO_DTV; | ||
253 | pads->flags = MEDIA_PAD_FL_SINK; | ||
254 | |||
255 | ret = media_entity_pads_init(entity, 1, pads); | ||
256 | if (ret < 0) | ||
257 | return ret; | ||
258 | |||
259 | ret = media_device_register_entity(dvbdev->adapter->mdev, | ||
260 | entity); | ||
261 | if (ret < 0) | ||
262 | return ret; | ||
263 | } | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | #define DEMUX_TSOUT "demux-tsout" | ||
268 | #define DVR_TSOUT "dvr-tsout" | ||
269 | |||
270 | static int dvb_create_media_entity(struct dvb_device *dvbdev, | ||
271 | int type, int demux_sink_pads) | ||
272 | { | ||
273 | int i, ret, npads; | ||
199 | 274 | ||
200 | switch (type) { | 275 | switch (type) { |
201 | case DVB_DEVICE_CA: | ||
202 | case DVB_DEVICE_DEMUX: | ||
203 | case DVB_DEVICE_FRONTEND: | 276 | case DVB_DEVICE_FRONTEND: |
204 | npads = 2; | 277 | npads = 2; |
205 | break; | 278 | break; |
206 | case DVB_DEVICE_NET: | 279 | case DVB_DEVICE_DVR: |
207 | npads = 0; | 280 | ret = dvb_create_tsout_entity(dvbdev, DVR_TSOUT, |
281 | demux_sink_pads); | ||
282 | return ret; | ||
283 | case DVB_DEVICE_DEMUX: | ||
284 | npads = 1 + demux_sink_pads; | ||
285 | ret = dvb_create_tsout_entity(dvbdev, DEMUX_TSOUT, | ||
286 | demux_sink_pads); | ||
287 | if (ret < 0) | ||
288 | return ret; | ||
289 | break; | ||
290 | case DVB_DEVICE_CA: | ||
291 | npads = 2; | ||
208 | break; | 292 | break; |
293 | case DVB_DEVICE_NET: | ||
294 | /* | ||
295 | * We should be creating entities for the MPE/ULE | ||
296 | * decapsulation hardware (or software implementation). | ||
297 | * | ||
298 | * However, the number of for the MPE/ULE decaps may not be | ||
299 | * fixed. As we don't have yet dynamic support for PADs at | ||
300 | * the Media Controller, let's not create the decap | ||
301 | * entities yet. | ||
302 | */ | ||
303 | return 0; | ||
209 | default: | 304 | default: |
210 | npads = 1; | 305 | return 0; |
211 | } | 306 | } |
212 | 307 | ||
308 | dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL); | ||
309 | if (!dvbdev->entity) | ||
310 | return -ENOMEM; | ||
311 | |||
312 | dvbdev->entity->name = dvbdev->name; | ||
313 | |||
213 | if (npads) { | 314 | if (npads) { |
214 | dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads), | 315 | dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads), |
215 | GFP_KERNEL); | 316 | GFP_KERNEL); |
216 | if (!dvbdev->pads) { | 317 | if (!dvbdev->pads) |
217 | kfree(dvbdev->entity); | 318 | return -ENOMEM; |
218 | return; | ||
219 | } | ||
220 | } | 319 | } |
221 | 320 | ||
222 | switch (type) { | 321 | switch (type) { |
223 | case DVB_DEVICE_FRONTEND: | 322 | case DVB_DEVICE_FRONTEND: |
224 | dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_FE; | 323 | dvbdev->entity->function = MEDIA_ENT_F_DTV_DEMOD; |
225 | dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; | 324 | dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; |
226 | dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; | 325 | dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; |
227 | break; | 326 | break; |
228 | case DVB_DEVICE_DEMUX: | 327 | case DVB_DEVICE_DEMUX: |
229 | dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DEMUX; | 328 | dvbdev->entity->function = MEDIA_ENT_F_TS_DEMUX; |
230 | dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; | ||
231 | dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; | ||
232 | break; | ||
233 | case DVB_DEVICE_DVR: | ||
234 | dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DVR; | ||
235 | dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; | 329 | dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; |
330 | for (i = 1; i < npads; i++) | ||
331 | dvbdev->pads[i].flags = MEDIA_PAD_FL_SOURCE; | ||
236 | break; | 332 | break; |
237 | case DVB_DEVICE_CA: | 333 | case DVB_DEVICE_CA: |
238 | dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA; | 334 | dvbdev->entity->function = MEDIA_ENT_F_DTV_CA; |
239 | dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; | 335 | dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; |
240 | dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; | 336 | dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; |
241 | break; | 337 | break; |
242 | case DVB_DEVICE_NET: | ||
243 | dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_NET; | ||
244 | break; | ||
245 | default: | 338 | default: |
339 | /* Should never happen, as the first switch prevents it */ | ||
246 | kfree(dvbdev->entity); | 340 | kfree(dvbdev->entity); |
341 | kfree(dvbdev->pads); | ||
247 | dvbdev->entity = NULL; | 342 | dvbdev->entity = NULL; |
248 | return; | 343 | dvbdev->pads = NULL; |
344 | return 0; | ||
249 | } | 345 | } |
250 | 346 | ||
251 | if (npads) | 347 | if (npads) { |
252 | ret = media_entity_init(dvbdev->entity, npads, dvbdev->pads, 0); | 348 | ret = media_entity_pads_init(dvbdev->entity, npads, dvbdev->pads); |
253 | if (!ret) | 349 | if (ret) |
254 | ret = media_device_register_entity(dvbdev->adapter->mdev, | 350 | return ret; |
255 | dvbdev->entity); | ||
256 | if (ret < 0) { | ||
257 | printk(KERN_ERR | ||
258 | "%s: media_device_register_entity failed for %s\n", | ||
259 | __func__, dvbdev->entity->name); | ||
260 | kfree(dvbdev->pads); | ||
261 | kfree(dvbdev->entity); | ||
262 | dvbdev->entity = NULL; | ||
263 | return; | ||
264 | } | 351 | } |
352 | ret = media_device_register_entity(dvbdev->adapter->mdev, | ||
353 | dvbdev->entity); | ||
354 | if (ret) | ||
355 | return (ret); | ||
265 | 356 | ||
266 | printk(KERN_DEBUG "%s: media device '%s' registered.\n", | 357 | printk(KERN_DEBUG "%s: media entity '%s' registered.\n", |
267 | __func__, dvbdev->entity->name); | 358 | __func__, dvbdev->entity->name); |
359 | |||
360 | return 0; | ||
361 | } | ||
362 | #endif | ||
363 | |||
364 | static int dvb_register_media_device(struct dvb_device *dvbdev, | ||
365 | int type, int minor, | ||
366 | unsigned demux_sink_pads) | ||
367 | { | ||
368 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) | ||
369 | struct media_link *link; | ||
370 | u32 intf_type; | ||
371 | int ret; | ||
372 | |||
373 | if (!dvbdev->adapter->mdev) | ||
374 | return 0; | ||
375 | |||
376 | ret = dvb_create_media_entity(dvbdev, type, demux_sink_pads); | ||
377 | if (ret) | ||
378 | return ret; | ||
379 | |||
380 | switch (type) { | ||
381 | case DVB_DEVICE_FRONTEND: | ||
382 | intf_type = MEDIA_INTF_T_DVB_FE; | ||
383 | break; | ||
384 | case DVB_DEVICE_DEMUX: | ||
385 | intf_type = MEDIA_INTF_T_DVB_DEMUX; | ||
386 | break; | ||
387 | case DVB_DEVICE_DVR: | ||
388 | intf_type = MEDIA_INTF_T_DVB_DVR; | ||
389 | break; | ||
390 | case DVB_DEVICE_CA: | ||
391 | intf_type = MEDIA_INTF_T_DVB_CA; | ||
392 | break; | ||
393 | case DVB_DEVICE_NET: | ||
394 | intf_type = MEDIA_INTF_T_DVB_NET; | ||
395 | break; | ||
396 | default: | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev, | ||
401 | intf_type, 0, | ||
402 | DVB_MAJOR, minor); | ||
403 | |||
404 | if (!dvbdev->intf_devnode) | ||
405 | return -ENOMEM; | ||
406 | |||
407 | /* | ||
408 | * Create the "obvious" link, e. g. the ones that represent | ||
409 | * a direct association between an interface and an entity. | ||
410 | * Other links should be created elsewhere, like: | ||
411 | * DVB FE intf -> tuner | ||
412 | * DVB demux intf -> dvr | ||
413 | */ | ||
414 | |||
415 | if (!dvbdev->entity) | ||
416 | return 0; | ||
417 | |||
418 | link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf, | ||
419 | MEDIA_LNK_FL_ENABLED); | ||
420 | if (!link) | ||
421 | return -ENOMEM; | ||
268 | #endif | 422 | #endif |
423 | return 0; | ||
269 | } | 424 | } |
270 | 425 | ||
271 | int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | 426 | int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, |
272 | const struct dvb_device *template, void *priv, int type) | 427 | const struct dvb_device *template, void *priv, int type, |
428 | int demux_sink_pads) | ||
273 | { | 429 | { |
274 | struct dvb_device *dvbdev; | 430 | struct dvb_device *dvbdev; |
275 | struct file_operations *dvbdevfops; | 431 | struct file_operations *dvbdevfops; |
276 | struct device *clsdev; | 432 | struct device *clsdev; |
277 | int minor; | 433 | int minor; |
278 | int id; | 434 | int id, ret; |
279 | 435 | ||
280 | mutex_lock(&dvbdev_register_lock); | 436 | mutex_lock(&dvbdev_register_lock); |
281 | 437 | ||
@@ -286,7 +442,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | |||
286 | return -ENFILE; | 442 | return -ENFILE; |
287 | } | 443 | } |
288 | 444 | ||
289 | *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL); | 445 | *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); |
290 | 446 | ||
291 | if (!dvbdev){ | 447 | if (!dvbdev){ |
292 | mutex_unlock(&dvbdev_register_lock); | 448 | mutex_unlock(&dvbdev_register_lock); |
@@ -335,6 +491,20 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | |||
335 | dvb_minors[minor] = dvbdev; | 491 | dvb_minors[minor] = dvbdev; |
336 | up_write(&minor_rwsem); | 492 | up_write(&minor_rwsem); |
337 | 493 | ||
494 | ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); | ||
495 | if (ret) { | ||
496 | printk(KERN_ERR | ||
497 | "%s: dvb_register_media_device failed to create the mediagraph\n", | ||
498 | __func__); | ||
499 | |||
500 | dvb_media_device_free(dvbdev); | ||
501 | kfree(dvbdevfops); | ||
502 | kfree(dvbdev); | ||
503 | up_write(&minor_rwsem); | ||
504 | mutex_unlock(&dvbdev_register_lock); | ||
505 | return ret; | ||
506 | } | ||
507 | |||
338 | mutex_unlock(&dvbdev_register_lock); | 508 | mutex_unlock(&dvbdev_register_lock); |
339 | 509 | ||
340 | clsdev = device_create(dvb_class, adap->device, | 510 | clsdev = device_create(dvb_class, adap->device, |
@@ -348,8 +518,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | |||
348 | dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", | 518 | dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", |
349 | adap->num, dnames[type], id, minor, minor); | 519 | adap->num, dnames[type], id, minor, minor); |
350 | 520 | ||
351 | dvb_register_media_device(dvbdev, type, minor); | ||
352 | |||
353 | return 0; | 521 | return 0; |
354 | } | 522 | } |
355 | EXPORT_SYMBOL(dvb_register_device); | 523 | EXPORT_SYMBOL(dvb_register_device); |
@@ -364,15 +532,9 @@ void dvb_unregister_device(struct dvb_device *dvbdev) | |||
364 | dvb_minors[dvbdev->minor] = NULL; | 532 | dvb_minors[dvbdev->minor] = NULL; |
365 | up_write(&minor_rwsem); | 533 | up_write(&minor_rwsem); |
366 | 534 | ||
367 | device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); | 535 | dvb_media_device_free(dvbdev); |
368 | 536 | ||
369 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) | 537 | device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); |
370 | if (dvbdev->entity) { | ||
371 | media_device_unregister_entity(dvbdev->entity); | ||
372 | kfree(dvbdev->entity); | ||
373 | kfree(dvbdev->pads); | ||
374 | } | ||
375 | #endif | ||
376 | 538 | ||
377 | list_del (&dvbdev->list_head); | 539 | list_del (&dvbdev->list_head); |
378 | kfree (dvbdev->fops); | 540 | kfree (dvbdev->fops); |
@@ -382,46 +544,212 @@ EXPORT_SYMBOL(dvb_unregister_device); | |||
382 | 544 | ||
383 | 545 | ||
384 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | 546 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB |
385 | void dvb_create_media_graph(struct dvb_adapter *adap) | 547 | |
548 | static int dvb_create_io_intf_links(struct dvb_adapter *adap, | ||
549 | struct media_interface *intf, | ||
550 | char *name) | ||
551 | { | ||
552 | struct media_device *mdev = adap->mdev; | ||
553 | struct media_entity *entity; | ||
554 | struct media_link *link; | ||
555 | |||
556 | media_device_for_each_entity(entity, mdev) { | ||
557 | if (entity->function == MEDIA_ENT_F_IO_DTV) { | ||
558 | if (strncmp(entity->name, name, strlen(name))) | ||
559 | continue; | ||
560 | link = media_create_intf_link(entity, intf, | ||
561 | MEDIA_LNK_FL_ENABLED); | ||
562 | if (!link) | ||
563 | return -ENOMEM; | ||
564 | } | ||
565 | } | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | int dvb_create_media_graph(struct dvb_adapter *adap, | ||
570 | bool create_rf_connector) | ||
386 | { | 571 | { |
387 | struct media_device *mdev = adap->mdev; | 572 | struct media_device *mdev = adap->mdev; |
388 | struct media_entity *entity, *tuner = NULL, *fe = NULL; | 573 | struct media_entity *entity, *tuner = NULL, *demod = NULL, *conn; |
389 | struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL; | 574 | struct media_entity *demux = NULL, *ca = NULL; |
575 | struct media_link *link; | ||
576 | struct media_interface *intf; | ||
577 | unsigned demux_pad = 0; | ||
578 | unsigned dvr_pad = 0; | ||
579 | unsigned ntuner = 0, ndemod = 0; | ||
580 | int ret; | ||
581 | static const char *connector_name = "Television"; | ||
390 | 582 | ||
391 | if (!mdev) | 583 | if (!mdev) |
392 | return; | 584 | return 0; |
393 | 585 | ||
394 | media_device_for_each_entity(entity, mdev) { | 586 | media_device_for_each_entity(entity, mdev) { |
395 | switch (entity->type) { | 587 | switch (entity->function) { |
396 | case MEDIA_ENT_T_V4L2_SUBDEV_TUNER: | 588 | case MEDIA_ENT_F_TUNER: |
397 | tuner = entity; | 589 | tuner = entity; |
590 | ntuner++; | ||
398 | break; | 591 | break; |
399 | case MEDIA_ENT_T_DEVNODE_DVB_FE: | 592 | case MEDIA_ENT_F_DTV_DEMOD: |
400 | fe = entity; | 593 | demod = entity; |
594 | ndemod++; | ||
401 | break; | 595 | break; |
402 | case MEDIA_ENT_T_DEVNODE_DVB_DEMUX: | 596 | case MEDIA_ENT_F_TS_DEMUX: |
403 | demux = entity; | 597 | demux = entity; |
404 | break; | 598 | break; |
405 | case MEDIA_ENT_T_DEVNODE_DVB_DVR: | 599 | case MEDIA_ENT_F_DTV_CA: |
406 | dvr = entity; | ||
407 | break; | ||
408 | case MEDIA_ENT_T_DEVNODE_DVB_CA: | ||
409 | ca = entity; | 600 | ca = entity; |
410 | break; | 601 | break; |
411 | } | 602 | } |
412 | } | 603 | } |
413 | 604 | ||
414 | if (tuner && fe) | 605 | /* |
415 | media_entity_create_link(tuner, 0, fe, 0, 0); | 606 | * Prepare to signalize to media_create_pad_links() that multiple |
607 | * entities of the same type exists and a 1:n or n:1 links need to be | ||
608 | * created. | ||
609 | * NOTE: if both tuner and demod have multiple instances, it is up | ||
610 | * to the caller driver to create such links. | ||
611 | */ | ||
612 | if (ntuner > 1) | ||
613 | tuner = NULL; | ||
614 | if (ndemod > 1) | ||
615 | demod = NULL; | ||
616 | |||
617 | if (create_rf_connector) { | ||
618 | conn = kzalloc(sizeof(*conn), GFP_KERNEL); | ||
619 | if (!conn) | ||
620 | return -ENOMEM; | ||
621 | adap->conn = conn; | ||
622 | |||
623 | adap->conn_pads = kcalloc(1, sizeof(*adap->conn_pads), | ||
624 | GFP_KERNEL); | ||
625 | if (!adap->conn_pads) | ||
626 | return -ENOMEM; | ||
627 | |||
628 | conn->flags = MEDIA_ENT_FL_CONNECTOR; | ||
629 | conn->function = MEDIA_ENT_F_CONN_RF; | ||
630 | conn->name = connector_name; | ||
631 | adap->conn_pads->flags = MEDIA_PAD_FL_SOURCE; | ||
632 | |||
633 | ret = media_entity_pads_init(conn, 1, adap->conn_pads); | ||
634 | if (ret) | ||
635 | return ret; | ||
636 | |||
637 | ret = media_device_register_entity(mdev, conn); | ||
638 | if (ret) | ||
639 | return ret; | ||
640 | |||
641 | if (!ntuner) | ||
642 | ret = media_create_pad_links(mdev, | ||
643 | MEDIA_ENT_F_CONN_RF, | ||
644 | conn, 0, | ||
645 | MEDIA_ENT_F_DTV_DEMOD, | ||
646 | demod, 0, | ||
647 | MEDIA_LNK_FL_ENABLED, | ||
648 | false); | ||
649 | else | ||
650 | ret = media_create_pad_links(mdev, | ||
651 | MEDIA_ENT_F_CONN_RF, | ||
652 | conn, 0, | ||
653 | MEDIA_ENT_F_TUNER, | ||
654 | tuner, TUNER_PAD_RF_INPUT, | ||
655 | MEDIA_LNK_FL_ENABLED, | ||
656 | false); | ||
657 | if (ret) | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | if (ntuner && ndemod) { | ||
662 | ret = media_create_pad_links(mdev, | ||
663 | MEDIA_ENT_F_TUNER, | ||
664 | tuner, TUNER_PAD_IF_OUTPUT, | ||
665 | MEDIA_ENT_F_DTV_DEMOD, | ||
666 | demod, 0, MEDIA_LNK_FL_ENABLED, | ||
667 | false); | ||
668 | if (ret) | ||
669 | return ret; | ||
670 | } | ||
671 | |||
672 | if (ndemod && demux) { | ||
673 | ret = media_create_pad_links(mdev, | ||
674 | MEDIA_ENT_F_DTV_DEMOD, | ||
675 | demod, 1, | ||
676 | MEDIA_ENT_F_TS_DEMUX, | ||
677 | demux, 0, MEDIA_LNK_FL_ENABLED, | ||
678 | false); | ||
679 | if (ret) | ||
680 | return -ENOMEM; | ||
681 | } | ||
682 | if (demux && ca) { | ||
683 | ret = media_create_pad_link(demux, 1, ca, | ||
684 | 0, MEDIA_LNK_FL_ENABLED); | ||
685 | if (!ret) | ||
686 | return -ENOMEM; | ||
687 | } | ||
416 | 688 | ||
417 | if (fe && demux) | 689 | /* Create demux links for each ringbuffer/pad */ |
418 | media_entity_create_link(fe, 1, demux, 0, MEDIA_LNK_FL_ENABLED); | 690 | if (demux) { |
691 | media_device_for_each_entity(entity, mdev) { | ||
692 | if (entity->function == MEDIA_ENT_F_IO_DTV) { | ||
693 | if (!strncmp(entity->name, DVR_TSOUT, | ||
694 | strlen(DVR_TSOUT))) { | ||
695 | ret = media_create_pad_link(demux, | ||
696 | ++dvr_pad, | ||
697 | entity, 0, 0); | ||
698 | if (ret) | ||
699 | return ret; | ||
700 | } | ||
701 | if (!strncmp(entity->name, DEMUX_TSOUT, | ||
702 | strlen(DEMUX_TSOUT))) { | ||
703 | ret = media_create_pad_link(demux, | ||
704 | ++demux_pad, | ||
705 | entity, 0, 0); | ||
706 | if (ret) | ||
707 | return ret; | ||
708 | } | ||
709 | } | ||
710 | } | ||
711 | } | ||
419 | 712 | ||
420 | if (demux && dvr) | 713 | /* Create interface links for FE->tuner, DVR->demux and CA->ca */ |
421 | media_entity_create_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED); | 714 | media_device_for_each_intf(intf, mdev) { |
715 | if (intf->type == MEDIA_INTF_T_DVB_CA && ca) { | ||
716 | link = media_create_intf_link(ca, intf, | ||
717 | MEDIA_LNK_FL_ENABLED); | ||
718 | if (!link) | ||
719 | return -ENOMEM; | ||
720 | } | ||
422 | 721 | ||
423 | if (demux && ca) | 722 | if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) { |
424 | media_entity_create_link(demux, 1, ca, 0, MEDIA_LNK_FL_ENABLED); | 723 | link = media_create_intf_link(tuner, intf, |
724 | MEDIA_LNK_FL_ENABLED); | ||
725 | if (!link) | ||
726 | return -ENOMEM; | ||
727 | } | ||
728 | #if 0 | ||
729 | /* | ||
730 | * Indirect link - let's not create yet, as we don't know how | ||
731 | * to handle indirect links, nor if this will | ||
732 | * actually be needed. | ||
733 | */ | ||
734 | if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) { | ||
735 | link = media_create_intf_link(demux, intf, | ||
736 | MEDIA_LNK_FL_ENABLED); | ||
737 | if (!link) | ||
738 | return -ENOMEM; | ||
739 | } | ||
740 | #endif | ||
741 | if (intf->type == MEDIA_INTF_T_DVB_DVR) { | ||
742 | ret = dvb_create_io_intf_links(adap, intf, DVR_TSOUT); | ||
743 | if (ret) | ||
744 | return ret; | ||
745 | } | ||
746 | if (intf->type == MEDIA_INTF_T_DVB_DEMUX) { | ||
747 | ret = dvb_create_io_intf_links(adap, intf, DEMUX_TSOUT); | ||
748 | if (ret) | ||
749 | return ret; | ||
750 | } | ||
751 | } | ||
752 | return 0; | ||
425 | } | 753 | } |
426 | EXPORT_SYMBOL_GPL(dvb_create_media_graph); | 754 | EXPORT_SYMBOL_GPL(dvb_create_media_graph); |
427 | #endif | 755 | #endif |
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h index 1069a776bbdb..4aff7bd3dea8 100644 --- a/drivers/media/dvb-core/dvbdev.h +++ b/drivers/media/dvb-core/dvbdev.h | |||
@@ -75,6 +75,9 @@ struct dvb_frontend; | |||
75 | * used. | 75 | * used. |
76 | * @mdev: pointer to struct media_device, used when the media | 76 | * @mdev: pointer to struct media_device, used when the media |
77 | * controller is used. | 77 | * controller is used. |
78 | * @conn: RF connector. Used only if the device has no separate | ||
79 | * tuner. | ||
80 | * @conn_pads: pointer to struct media_pad associated with @conn; | ||
78 | */ | 81 | */ |
79 | struct dvb_adapter { | 82 | struct dvb_adapter { |
80 | int num; | 83 | int num; |
@@ -94,6 +97,8 @@ struct dvb_adapter { | |||
94 | 97 | ||
95 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) | 98 | #if defined(CONFIG_MEDIA_CONTROLLER_DVB) |
96 | struct media_device *mdev; | 99 | struct media_device *mdev; |
100 | struct media_entity *conn; | ||
101 | struct media_pad *conn_pads; | ||
97 | #endif | 102 | #endif |
98 | }; | 103 | }; |
99 | 104 | ||
@@ -120,6 +125,11 @@ struct dvb_adapter { | |||
120 | * @entity: pointer to struct media_entity associated with the device node | 125 | * @entity: pointer to struct media_entity associated with the device node |
121 | * @pads: pointer to struct media_pad associated with @entity; | 126 | * @pads: pointer to struct media_pad associated with @entity; |
122 | * @priv: private data | 127 | * @priv: private data |
128 | * @intf_devnode: Pointer to media_intf_devnode. Used by the dvbdev core to | ||
129 | * store the MC device node interface | ||
130 | * @tsout_num_entities: Number of Transport Stream output entities | ||
131 | * @tsout_entity: array with MC entities associated to each TS output node | ||
132 | * @tsout_pads: array with the source pads for each @tsout_entity | ||
123 | * | 133 | * |
124 | * This structure is used by the DVB core (frontend, CA, net, demux) in | 134 | * This structure is used by the DVB core (frontend, CA, net, demux) in |
125 | * order to create the device nodes. Usually, driver should not initialize | 135 | * order to create the device nodes. Usually, driver should not initialize |
@@ -148,8 +158,11 @@ struct dvb_device { | |||
148 | const char *name; | 158 | const char *name; |
149 | 159 | ||
150 | /* Allocated and filled inside dvbdev.c */ | 160 | /* Allocated and filled inside dvbdev.c */ |
151 | struct media_entity *entity; | 161 | struct media_intf_devnode *intf_devnode; |
152 | struct media_pad *pads; | 162 | |
163 | unsigned tsout_num_entities; | ||
164 | struct media_entity *entity, *tsout_entity; | ||
165 | struct media_pad *pads, *tsout_pads; | ||
153 | #endif | 166 | #endif |
154 | 167 | ||
155 | void *priv; | 168 | void *priv; |
@@ -185,14 +198,18 @@ int dvb_unregister_adapter(struct dvb_adapter *adap); | |||
185 | * stored | 198 | * stored |
186 | * @template: Template used to create &pdvbdev; | 199 | * @template: Template used to create &pdvbdev; |
187 | * @priv: private data | 200 | * @priv: private data |
188 | * @type: type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND, | 201 | * @type: type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND, |
189 | * DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET | 202 | * %DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA, |
203 | * %DVB_DEVICE_NET | ||
204 | * @demux_sink_pads: Number of demux outputs, to be used to create the TS | ||
205 | * outputs via the Media Controller. | ||
190 | */ | 206 | */ |
191 | int dvb_register_device(struct dvb_adapter *adap, | 207 | int dvb_register_device(struct dvb_adapter *adap, |
192 | struct dvb_device **pdvbdev, | 208 | struct dvb_device **pdvbdev, |
193 | const struct dvb_device *template, | 209 | const struct dvb_device *template, |
194 | void *priv, | 210 | void *priv, |
195 | int type); | 211 | int type, |
212 | int demux_sink_pads); | ||
196 | 213 | ||
197 | /** | 214 | /** |
198 | * dvb_unregister_device - Unregisters a DVB device | 215 | * dvb_unregister_device - Unregisters a DVB device |
@@ -202,16 +219,43 @@ int dvb_register_device(struct dvb_adapter *adap, | |||
202 | void dvb_unregister_device(struct dvb_device *dvbdev); | 219 | void dvb_unregister_device(struct dvb_device *dvbdev); |
203 | 220 | ||
204 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | 221 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB |
205 | void dvb_create_media_graph(struct dvb_adapter *adap); | 222 | /** |
223 | * dvb_create_media_graph - Creates media graph for the Digital TV part of the | ||
224 | * device. | ||
225 | * | ||
226 | * @adap: pointer to struct dvb_adapter | ||
227 | * @create_rf_connector: if true, it creates the RF connector too | ||
228 | * | ||
229 | * This function checks all DVB-related functions at the media controller | ||
230 | * entities and creates the needed links for the media graph. It is | ||
231 | * capable of working with multiple tuners or multiple frontends, but it | ||
232 | * won't create links if the device has multiple tuners and multiple frontends | ||
233 | * or if the device has multiple muxes. In such case, the caller driver should | ||
234 | * manually create the remaining links. | ||
235 | */ | ||
236 | __must_check int dvb_create_media_graph(struct dvb_adapter *adap, | ||
237 | bool create_rf_connector); | ||
238 | |||
206 | static inline void dvb_register_media_controller(struct dvb_adapter *adap, | 239 | static inline void dvb_register_media_controller(struct dvb_adapter *adap, |
207 | struct media_device *mdev) | 240 | struct media_device *mdev) |
208 | { | 241 | { |
209 | adap->mdev = mdev; | 242 | adap->mdev = mdev; |
210 | } | 243 | } |
211 | 244 | ||
245 | static inline struct media_device | ||
246 | *dvb_get_media_controller(struct dvb_adapter *adap) | ||
247 | { | ||
248 | return adap->mdev; | ||
249 | } | ||
212 | #else | 250 | #else |
213 | static inline void dvb_create_media_graph(struct dvb_adapter *adap) {} | 251 | static inline |
252 | int dvb_create_media_graph(struct dvb_adapter *adap, | ||
253 | bool create_rf_connector) | ||
254 | { | ||
255 | return 0; | ||
256 | }; | ||
214 | #define dvb_register_media_controller(a, b) {} | 257 | #define dvb_register_media_controller(a, b) {} |
258 | #define dvb_get_media_controller(a) NULL | ||
215 | #endif | 259 | #endif |
216 | 260 | ||
217 | int dvb_generic_open (struct inode *inode, struct file *file); | 261 | int dvb_generic_open (struct inode *inode, struct file *file); |
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index c8f13d8370e5..73612c5353d1 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c | |||
@@ -730,6 +730,9 @@ static int au8522_probe(struct i2c_client *client, | |||
730 | struct v4l2_ctrl_handler *hdl; | 730 | struct v4l2_ctrl_handler *hdl; |
731 | struct v4l2_subdev *sd; | 731 | struct v4l2_subdev *sd; |
732 | int instance; | 732 | int instance; |
733 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
734 | int ret; | ||
735 | #endif | ||
733 | 736 | ||
734 | /* Check if the adapter supports the needed features */ | 737 | /* Check if the adapter supports the needed features */ |
735 | if (!i2c_check_functionality(client->adapter, | 738 | if (!i2c_check_functionality(client->adapter, |
@@ -758,6 +761,20 @@ static int au8522_probe(struct i2c_client *client, | |||
758 | 761 | ||
759 | sd = &state->sd; | 762 | sd = &state->sd; |
760 | v4l2_i2c_subdev_init(sd, client, &au8522_ops); | 763 | v4l2_i2c_subdev_init(sd, client, &au8522_ops); |
764 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
765 | |||
766 | state->pads[AU8522_PAD_INPUT].flags = MEDIA_PAD_FL_SINK; | ||
767 | state->pads[AU8522_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; | ||
768 | state->pads[AU8522_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; | ||
769 | sd->entity.function = MEDIA_ENT_F_ATV_DECODER; | ||
770 | |||
771 | ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads), | ||
772 | state->pads); | ||
773 | if (ret < 0) { | ||
774 | v4l_info(client, "failed to initialize media entity!\n"); | ||
775 | return ret; | ||
776 | } | ||
777 | #endif | ||
761 | 778 | ||
762 | hdl = &state->hdl; | 779 | hdl = &state->hdl; |
763 | v4l2_ctrl_handler_init(hdl, 4); | 780 | v4l2_ctrl_handler_init(hdl, 4); |
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h index ee330c61aa61..404a0cb0ed8d 100644 --- a/drivers/media/dvb-frontends/au8522_priv.h +++ b/drivers/media/dvb-frontends/au8522_priv.h | |||
@@ -39,6 +39,14 @@ | |||
39 | #define AU8522_DIGITAL_MODE 1 | 39 | #define AU8522_DIGITAL_MODE 1 |
40 | #define AU8522_SUSPEND_MODE 2 | 40 | #define AU8522_SUSPEND_MODE 2 |
41 | 41 | ||
42 | enum au8522_media_pads { | ||
43 | AU8522_PAD_INPUT, | ||
44 | AU8522_PAD_VID_OUT, | ||
45 | AU8522_PAD_VBI_OUT, | ||
46 | |||
47 | AU8522_NUM_PADS | ||
48 | }; | ||
49 | |||
42 | struct au8522_state { | 50 | struct au8522_state { |
43 | struct i2c_client *c; | 51 | struct i2c_client *c; |
44 | struct i2c_adapter *i2c; | 52 | struct i2c_adapter *i2c; |
@@ -68,6 +76,10 @@ struct au8522_state { | |||
68 | u32 id; | 76 | u32 id; |
69 | u32 rev; | 77 | u32 rev; |
70 | struct v4l2_ctrl_handler hdl; | 78 | struct v4l2_ctrl_handler hdl; |
79 | |||
80 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
81 | struct media_pad pads[AU8522_NUM_PADS]; | ||
82 | #endif | ||
71 | }; | 83 | }; |
72 | 84 | ||
73 | /* These are routines shared by both the VSB/QAM demodulator and the analog | 85 | /* These are routines shared by both the VSB/QAM demodulator and the analog |
diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c index e63f582378bf..edbb30fdd9d9 100644 --- a/drivers/media/firewire/firedtv-ci.c +++ b/drivers/media/firewire/firedtv-ci.c | |||
@@ -241,7 +241,7 @@ int fdtv_ca_register(struct firedtv *fdtv) | |||
241 | return -EFAULT; | 241 | return -EFAULT; |
242 | 242 | ||
243 | err = dvb_register_device(&fdtv->adapter, &fdtv->cadev, | 243 | err = dvb_register_device(&fdtv->adapter, &fdtv->cadev, |
244 | &fdtv_ca, fdtv, DVB_DEVICE_CA); | 244 | &fdtv_ca, fdtv, DVB_DEVICE_CA, 0); |
245 | 245 | ||
246 | if (stat.ca_application_info == 0) | 246 | if (stat.ca_application_info == 0) |
247 | dev_err(fdtv->device, "CaApplicationInfo is not set\n"); | 247 | dev_err(fdtv->device, "CaApplicationInfo is not set\n"); |
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 0494a7896aa2..788967dadd29 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c | |||
@@ -1158,7 +1158,7 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * | |||
1158 | state->rgb_quantization_range_ctrl->is_private = true; | 1158 | state->rgb_quantization_range_ctrl->is_private = true; |
1159 | 1159 | ||
1160 | state->pad.flags = MEDIA_PAD_FL_SINK; | 1160 | state->pad.flags = MEDIA_PAD_FL_SINK; |
1161 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | 1161 | err = media_entity_pads_init(&sd->entity, 1, &state->pad); |
1162 | if (err) | 1162 | if (err) |
1163 | goto err_hdl; | 1163 | goto err_hdl; |
1164 | 1164 | ||
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index f00745bbe471..7e9cbf757e95 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c | |||
@@ -512,11 +512,11 @@ static int adp1653_probe(struct i2c_client *client, | |||
512 | if (ret) | 512 | if (ret) |
513 | goto free_and_quit; | 513 | goto free_and_quit; |
514 | 514 | ||
515 | ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0); | 515 | ret = media_entity_pads_init(&flash->subdev.entity, 0, NULL); |
516 | if (ret < 0) | 516 | if (ret < 0) |
517 | goto free_and_quit; | 517 | goto free_and_quit; |
518 | 518 | ||
519 | flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH; | 519 | flash->subdev.entity.function = MEDIA_ENT_F_FLASH; |
520 | 520 | ||
521 | return 0; | 521 | return 0; |
522 | 522 | ||
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 3c3c4bfe3866..ff57c1dcb8af 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c | |||
@@ -1213,8 +1213,8 @@ static int adv7180_probe(struct i2c_client *client, | |||
1213 | goto err_unregister_vpp_client; | 1213 | goto err_unregister_vpp_client; |
1214 | 1214 | ||
1215 | state->pad.flags = MEDIA_PAD_FL_SOURCE; | 1215 | state->pad.flags = MEDIA_PAD_FL_SOURCE; |
1216 | sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; | 1216 | sd->entity.flags |= MEDIA_ENT_F_ATV_DECODER; |
1217 | ret = media_entity_init(&sd->entity, 1, &state->pad, 0); | 1217 | ret = media_entity_pads_init(&sd->entity, 1, &state->pad); |
1218 | if (ret) | 1218 | if (ret) |
1219 | goto err_free_ctrl; | 1219 | goto err_free_ctrl; |
1220 | 1220 | ||
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index eeb2cd823c4d..471fd23b5c5c 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c | |||
@@ -1482,7 +1482,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * | |||
1482 | state->rgb_quantization_range_ctrl->is_private = true; | 1482 | state->rgb_quantization_range_ctrl->is_private = true; |
1483 | 1483 | ||
1484 | state->pad.flags = MEDIA_PAD_FL_SINK; | 1484 | state->pad.flags = MEDIA_PAD_FL_SINK; |
1485 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | 1485 | err = media_entity_pads_init(&sd->entity, 1, &state->pad); |
1486 | if (err) | 1486 | if (err) |
1487 | goto err_hdl; | 1487 | goto err_hdl; |
1488 | 1488 | ||
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 745286225655..f8dd7505b529 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c | |||
@@ -3208,8 +3208,8 @@ static int adv76xx_probe(struct i2c_client *client, | |||
3208 | state->pads[i].flags = MEDIA_PAD_FL_SINK; | 3208 | state->pads[i].flags = MEDIA_PAD_FL_SINK; |
3209 | state->pads[state->source_pad].flags = MEDIA_PAD_FL_SOURCE; | 3209 | state->pads[state->source_pad].flags = MEDIA_PAD_FL_SOURCE; |
3210 | 3210 | ||
3211 | err = media_entity_init(&sd->entity, state->source_pad + 1, | 3211 | err = media_entity_pads_init(&sd->entity, state->source_pad + 1, |
3212 | state->pads, 0); | 3212 | state->pads); |
3213 | if (err) | 3213 | if (err) |
3214 | goto err_work_queues; | 3214 | goto err_work_queues; |
3215 | 3215 | ||
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 69378e4914b6..5fbb788e7b59 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c | |||
@@ -3309,7 +3309,7 @@ static int adv7842_probe(struct i2c_client *client, | |||
3309 | adv7842_delayed_work_enable_hotplug); | 3309 | adv7842_delayed_work_enable_hotplug); |
3310 | 3310 | ||
3311 | state->pad.flags = MEDIA_PAD_FL_SOURCE; | 3311 | state->pad.flags = MEDIA_PAD_FL_SOURCE; |
3312 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | 3312 | err = media_entity_pads_init(&sd->entity, 1, &state->pad); |
3313 | if (err) | 3313 | if (err) |
3314 | goto err_work_queues; | 3314 | goto err_work_queues; |
3315 | 3315 | ||
diff --git a/drivers/media/i2c/as3645a.c b/drivers/media/i2c/as3645a.c index 29a2e7034aa6..2e90e4094b79 100644 --- a/drivers/media/i2c/as3645a.c +++ b/drivers/media/i2c/as3645a.c | |||
@@ -827,11 +827,11 @@ static int as3645a_probe(struct i2c_client *client, | |||
827 | if (ret < 0) | 827 | if (ret < 0) |
828 | goto done; | 828 | goto done; |
829 | 829 | ||
830 | ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0); | 830 | ret = media_entity_pads_init(&flash->subdev.entity, 0, NULL); |
831 | if (ret < 0) | 831 | if (ret < 0) |
832 | goto done; | 832 | goto done; |
833 | 833 | ||
834 | flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH; | 834 | flash->subdev.entity.function = MEDIA_ENT_F_FLASH; |
835 | 835 | ||
836 | mutex_init(&flash->power_lock); | 836 | mutex_init(&flash->power_lock); |
837 | 837 | ||
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index f2e2c34ddbbd..07a3e7173144 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c | |||
@@ -5211,10 +5211,10 @@ static int cx25840_probe(struct i2c_client *client, | |||
5211 | state->pads[CX25840_PAD_INPUT].flags = MEDIA_PAD_FL_SINK; | 5211 | state->pads[CX25840_PAD_INPUT].flags = MEDIA_PAD_FL_SINK; |
5212 | state->pads[CX25840_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; | 5212 | state->pads[CX25840_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; |
5213 | state->pads[CX25840_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; | 5213 | state->pads[CX25840_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; |
5214 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_DECODER; | 5214 | sd->entity.function = MEDIA_ENT_F_ATV_DECODER; |
5215 | 5215 | ||
5216 | ret = media_entity_init(&sd->entity, ARRAY_SIZE(state->pads), | 5216 | ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads), |
5217 | state->pads, 0); | 5217 | state->pads); |
5218 | if (ret < 0) { | 5218 | if (ret < 0) { |
5219 | v4l_info(client, "failed to initialize media entity!\n"); | 5219 | v4l_info(client, "failed to initialize media entity!\n"); |
5220 | return ret; | 5220 | return ret; |
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index 19ecb8801064..251a2aaf98c3 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c | |||
@@ -365,10 +365,10 @@ static int lm3560_subdev_init(struct lm3560_flash *flash, | |||
365 | rval = lm3560_init_controls(flash, led_no); | 365 | rval = lm3560_init_controls(flash, led_no); |
366 | if (rval) | 366 | if (rval) |
367 | goto err_out; | 367 | goto err_out; |
368 | rval = media_entity_init(&flash->subdev_led[led_no].entity, 0, NULL, 0); | 368 | rval = media_entity_pads_init(&flash->subdev_led[led_no].entity, 0, NULL); |
369 | if (rval < 0) | 369 | if (rval < 0) |
370 | goto err_out; | 370 | goto err_out; |
371 | flash->subdev_led[led_no].entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH; | 371 | flash->subdev_led[led_no].entity.function = MEDIA_ENT_F_FLASH; |
372 | 372 | ||
373 | return rval; | 373 | return rval; |
374 | 374 | ||
diff --git a/drivers/media/i2c/lm3646.c b/drivers/media/i2c/lm3646.c index 7fbe6ff1c4f4..7e9967af36ec 100644 --- a/drivers/media/i2c/lm3646.c +++ b/drivers/media/i2c/lm3646.c | |||
@@ -282,10 +282,10 @@ static int lm3646_subdev_init(struct lm3646_flash *flash) | |||
282 | rval = lm3646_init_controls(flash); | 282 | rval = lm3646_init_controls(flash); |
283 | if (rval) | 283 | if (rval) |
284 | goto err_out; | 284 | goto err_out; |
285 | rval = media_entity_init(&flash->subdev_led.entity, 0, NULL, 0); | 285 | rval = media_entity_pads_init(&flash->subdev_led.entity, 0, NULL); |
286 | if (rval < 0) | 286 | if (rval < 0) |
287 | goto err_out; | 287 | goto err_out; |
288 | flash->subdev_led.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH; | 288 | flash->subdev_led.entity.function = MEDIA_ENT_F_FLASH; |
289 | return rval; | 289 | return rval; |
290 | 290 | ||
291 | err_out: | 291 | err_out: |
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index f8993933416e..acb804bceccb 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c | |||
@@ -975,10 +975,10 @@ static int m5mols_probe(struct i2c_client *client, | |||
975 | 975 | ||
976 | sd->internal_ops = &m5mols_subdev_internal_ops; | 976 | sd->internal_ops = &m5mols_subdev_internal_ops; |
977 | info->pad.flags = MEDIA_PAD_FL_SOURCE; | 977 | info->pad.flags = MEDIA_PAD_FL_SOURCE; |
978 | ret = media_entity_init(&sd->entity, 1, &info->pad, 0); | 978 | ret = media_entity_pads_init(&sd->entity, 1, &info->pad); |
979 | if (ret < 0) | 979 | if (ret < 0) |
980 | return ret; | 980 | return ret; |
981 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 981 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
982 | 982 | ||
983 | init_waitqueue_head(&info->irq_waitq); | 983 | init_waitqueue_head(&info->irq_waitq); |
984 | mutex_init(&info->lock); | 984 | mutex_init(&info->lock); |
diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c index 101cb26f9330..da076796999e 100644 --- a/drivers/media/i2c/mt9m032.c +++ b/drivers/media/i2c/mt9m032.c | |||
@@ -799,7 +799,7 @@ static int mt9m032_probe(struct i2c_client *client, | |||
799 | 799 | ||
800 | sensor->subdev.ctrl_handler = &sensor->ctrls; | 800 | sensor->subdev.ctrl_handler = &sensor->ctrls; |
801 | sensor->pad.flags = MEDIA_PAD_FL_SOURCE; | 801 | sensor->pad.flags = MEDIA_PAD_FL_SOURCE; |
802 | ret = media_entity_init(&sensor->subdev.entity, 1, &sensor->pad, 0); | 802 | ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad); |
803 | if (ret < 0) | 803 | if (ret < 0) |
804 | goto error_ctrl; | 804 | goto error_ctrl; |
805 | 805 | ||
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index a3da0e977d0b..237737fec09c 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c | |||
@@ -1112,7 +1112,7 @@ static int mt9p031_probe(struct i2c_client *client, | |||
1112 | mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops; | 1112 | mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops; |
1113 | 1113 | ||
1114 | mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE; | 1114 | mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE; |
1115 | ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0); | 1115 | ret = media_entity_pads_init(&mt9p031->subdev.entity, 1, &mt9p031->pad); |
1116 | if (ret < 0) | 1116 | if (ret < 0) |
1117 | goto done; | 1117 | goto done; |
1118 | 1118 | ||
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c index b28fdff1d310..702d562f8e39 100644 --- a/drivers/media/i2c/mt9t001.c +++ b/drivers/media/i2c/mt9t001.c | |||
@@ -933,7 +933,7 @@ static int mt9t001_probe(struct i2c_client *client, | |||
933 | mt9t001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 933 | mt9t001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
934 | 934 | ||
935 | mt9t001->pad.flags = MEDIA_PAD_FL_SOURCE; | 935 | mt9t001->pad.flags = MEDIA_PAD_FL_SOURCE; |
936 | ret = media_entity_init(&mt9t001->subdev.entity, 1, &mt9t001->pad, 0); | 936 | ret = media_entity_pads_init(&mt9t001->subdev.entity, 1, &mt9t001->pad); |
937 | 937 | ||
938 | done: | 938 | done: |
939 | if (ret < 0) { | 939 | if (ret < 0) { |
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 1dbbd23fdfb0..2e1d116a64e7 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c | |||
@@ -1046,7 +1046,7 @@ static int mt9v032_probe(struct i2c_client *client, | |||
1046 | mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1046 | mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1047 | 1047 | ||
1048 | mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; | 1048 | mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; |
1049 | ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0); | 1049 | ret = media_entity_pads_init(&mt9v032->subdev.entity, 1, &mt9v032->pad); |
1050 | if (ret < 0) | 1050 | if (ret < 0) |
1051 | goto err; | 1051 | goto err; |
1052 | 1052 | ||
diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index 69e4f3031d8b..30cb90b88d75 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c | |||
@@ -779,8 +779,8 @@ static int noon010_probe(struct i2c_client *client, | |||
779 | goto np_err; | 779 | goto np_err; |
780 | 780 | ||
781 | info->pad.flags = MEDIA_PAD_FL_SOURCE; | 781 | info->pad.flags = MEDIA_PAD_FL_SOURCE; |
782 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 782 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
783 | ret = media_entity_init(&sd->entity, 1, &info->pad, 0); | 783 | ret = media_entity_pads_init(&sd->entity, 1, &info->pad); |
784 | if (ret < 0) | 784 | if (ret < 0) |
785 | goto np_err; | 785 | goto np_err; |
786 | 786 | ||
diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 82c7ac1cc88e..02b9a3440557 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c | |||
@@ -1445,8 +1445,8 @@ static int ov2659_probe(struct i2c_client *client, | |||
1445 | 1445 | ||
1446 | #if defined(CONFIG_MEDIA_CONTROLLER) | 1446 | #if defined(CONFIG_MEDIA_CONTROLLER) |
1447 | ov2659->pad.flags = MEDIA_PAD_FL_SOURCE; | 1447 | ov2659->pad.flags = MEDIA_PAD_FL_SOURCE; |
1448 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 1448 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1449 | ret = media_entity_init(&sd->entity, 1, &ov2659->pad, 0); | 1449 | ret = media_entity_pads_init(&sd->entity, 1, &ov2659->pad); |
1450 | if (ret < 0) { | 1450 | if (ret < 0) { |
1451 | v4l2_ctrl_handler_free(&ov2659->ctrls); | 1451 | v4l2_ctrl_handler_free(&ov2659->ctrls); |
1452 | return ret; | 1452 | return ret; |
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 9fe9006474b2..a0b3c9bde53d 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c | |||
@@ -1500,8 +1500,8 @@ static int ov965x_probe(struct i2c_client *client, | |||
1500 | return ret; | 1500 | return ret; |
1501 | 1501 | ||
1502 | ov965x->pad.flags = MEDIA_PAD_FL_SOURCE; | 1502 | ov965x->pad.flags = MEDIA_PAD_FL_SOURCE; |
1503 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 1503 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1504 | ret = media_entity_init(&sd->entity, 1, &ov965x->pad, 0); | 1504 | ret = media_entity_pads_init(&sd->entity, 1, &ov965x->pad); |
1505 | if (ret < 0) | 1505 | if (ret < 0) |
1506 | return ret; | 1506 | return ret; |
1507 | 1507 | ||
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 25f5e79dc9bc..57b3d27993a4 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c | |||
@@ -1482,11 +1482,11 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd) | |||
1482 | return ret; | 1482 | return ret; |
1483 | } | 1483 | } |
1484 | 1484 | ||
1485 | ret = media_entity_create_link(&state->sensor_sd.entity, | 1485 | ret = media_create_pad_link(&state->sensor_sd.entity, |
1486 | S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD, | 1486 | S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD, |
1487 | MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); | 1487 | MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); |
1488 | 1488 | ||
1489 | ret = media_entity_create_link(&state->sensor_sd.entity, | 1489 | ret = media_create_pad_link(&state->sensor_sd.entity, |
1490 | S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD, | 1490 | S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD, |
1491 | MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); | 1491 | MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); |
1492 | 1492 | ||
@@ -1688,10 +1688,10 @@ static int s5c73m3_probe(struct i2c_client *client, | |||
1688 | 1688 | ||
1689 | state->sensor_pads[S5C73M3_JPEG_PAD].flags = MEDIA_PAD_FL_SOURCE; | 1689 | state->sensor_pads[S5C73M3_JPEG_PAD].flags = MEDIA_PAD_FL_SOURCE; |
1690 | state->sensor_pads[S5C73M3_ISP_PAD].flags = MEDIA_PAD_FL_SOURCE; | 1690 | state->sensor_pads[S5C73M3_ISP_PAD].flags = MEDIA_PAD_FL_SOURCE; |
1691 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV; | 1691 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1692 | 1692 | ||
1693 | ret = media_entity_init(&sd->entity, S5C73M3_NUM_PADS, | 1693 | ret = media_entity_pads_init(&sd->entity, S5C73M3_NUM_PADS, |
1694 | state->sensor_pads, 0); | 1694 | state->sensor_pads); |
1695 | if (ret < 0) | 1695 | if (ret < 0) |
1696 | return ret; | 1696 | return ret; |
1697 | 1697 | ||
@@ -1704,10 +1704,10 @@ static int s5c73m3_probe(struct i2c_client *client, | |||
1704 | state->oif_pads[OIF_ISP_PAD].flags = MEDIA_PAD_FL_SINK; | 1704 | state->oif_pads[OIF_ISP_PAD].flags = MEDIA_PAD_FL_SINK; |
1705 | state->oif_pads[OIF_JPEG_PAD].flags = MEDIA_PAD_FL_SINK; | 1705 | state->oif_pads[OIF_JPEG_PAD].flags = MEDIA_PAD_FL_SINK; |
1706 | state->oif_pads[OIF_SOURCE_PAD].flags = MEDIA_PAD_FL_SOURCE; | 1706 | state->oif_pads[OIF_SOURCE_PAD].flags = MEDIA_PAD_FL_SOURCE; |
1707 | oif_sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV; | 1707 | oif_sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; |
1708 | 1708 | ||
1709 | ret = media_entity_init(&oif_sd->entity, OIF_NUM_PADS, | 1709 | ret = media_entity_pads_init(&oif_sd->entity, OIF_NUM_PADS, |
1710 | state->oif_pads, 0); | 1710 | state->oif_pads); |
1711 | if (ret < 0) | 1711 | if (ret < 0) |
1712 | return ret; | 1712 | return ret; |
1713 | 1713 | ||
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c index 6757aca2cdab..8a0f22da590f 100644 --- a/drivers/media/i2c/s5k4ecgx.c +++ b/drivers/media/i2c/s5k4ecgx.c | |||
@@ -961,8 +961,8 @@ static int s5k4ecgx_probe(struct i2c_client *client, | |||
961 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 961 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
962 | 962 | ||
963 | priv->pad.flags = MEDIA_PAD_FL_SOURCE; | 963 | priv->pad.flags = MEDIA_PAD_FL_SOURCE; |
964 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 964 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
965 | ret = media_entity_init(&sd->entity, 1, &priv->pad, 0); | 965 | ret = media_entity_pads_init(&sd->entity, 1, &priv->pad); |
966 | if (ret) | 966 | if (ret) |
967 | return ret; | 967 | return ret; |
968 | 968 | ||
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 774e0d0c94cb..fc3a5a8e6c9c 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c | |||
@@ -408,7 +408,7 @@ static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) | |||
408 | 408 | ||
409 | static inline bool s5k5baf_is_cis_subdev(struct v4l2_subdev *sd) | 409 | static inline bool s5k5baf_is_cis_subdev(struct v4l2_subdev *sd) |
410 | { | 410 | { |
411 | return sd->entity.type == MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 411 | return sd->entity.function == MEDIA_ENT_F_CAM_SENSOR; |
412 | } | 412 | } |
413 | 413 | ||
414 | static inline struct s5k5baf *to_s5k5baf(struct v4l2_subdev *sd) | 414 | static inline struct s5k5baf *to_s5k5baf(struct v4l2_subdev *sd) |
@@ -1756,7 +1756,7 @@ static int s5k5baf_registered(struct v4l2_subdev *sd) | |||
1756 | v4l2_err(sd, "failed to register subdev %s\n", | 1756 | v4l2_err(sd, "failed to register subdev %s\n", |
1757 | state->cis_sd.name); | 1757 | state->cis_sd.name); |
1758 | else | 1758 | else |
1759 | ret = media_entity_create_link(&state->cis_sd.entity, PAD_CIS, | 1759 | ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS, |
1760 | &state->sd.entity, PAD_CIS, | 1760 | &state->sd.entity, PAD_CIS, |
1761 | MEDIA_LNK_FL_IMMUTABLE | | 1761 | MEDIA_LNK_FL_IMMUTABLE | |
1762 | MEDIA_LNK_FL_ENABLED); | 1762 | MEDIA_LNK_FL_ENABLED); |
@@ -1904,8 +1904,8 @@ static int s5k5baf_configure_subdevs(struct s5k5baf *state, | |||
1904 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1904 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1905 | 1905 | ||
1906 | state->cis_pad.flags = MEDIA_PAD_FL_SOURCE; | 1906 | state->cis_pad.flags = MEDIA_PAD_FL_SOURCE; |
1907 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 1907 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1908 | ret = media_entity_init(&sd->entity, NUM_CIS_PADS, &state->cis_pad, 0); | 1908 | ret = media_entity_pads_init(&sd->entity, NUM_CIS_PADS, &state->cis_pad); |
1909 | if (ret < 0) | 1909 | if (ret < 0) |
1910 | goto err; | 1910 | goto err; |
1911 | 1911 | ||
@@ -1919,8 +1919,8 @@ static int s5k5baf_configure_subdevs(struct s5k5baf *state, | |||
1919 | 1919 | ||
1920 | state->pads[PAD_CIS].flags = MEDIA_PAD_FL_SINK; | 1920 | state->pads[PAD_CIS].flags = MEDIA_PAD_FL_SINK; |
1921 | state->pads[PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; | 1921 | state->pads[PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; |
1922 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV; | 1922 | sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; |
1923 | ret = media_entity_init(&sd->entity, NUM_ISP_PADS, state->pads, 0); | 1923 | ret = media_entity_pads_init(&sd->entity, NUM_ISP_PADS, state->pads); |
1924 | 1924 | ||
1925 | if (!ret) | 1925 | if (!ret) |
1926 | return 0; | 1926 | return 0; |
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index b1b1574dfb95..b9e43ffa5085 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c | |||
@@ -333,7 +333,7 @@ static int s5k6a3_probe(struct i2c_client *client, | |||
333 | sensor->format.height = S5K6A3_DEFAULT_HEIGHT; | 333 | sensor->format.height = S5K6A3_DEFAULT_HEIGHT; |
334 | 334 | ||
335 | sensor->pad.flags = MEDIA_PAD_FL_SOURCE; | 335 | sensor->pad.flags = MEDIA_PAD_FL_SOURCE; |
336 | ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0); | 336 | ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad); |
337 | if (ret < 0) | 337 | if (ret < 0) |
338 | return ret; | 338 | return ret; |
339 | 339 | ||
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 60aaff7190d2..faee11383cb7 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c | |||
@@ -1577,8 +1577,8 @@ static int s5k6aa_probe(struct i2c_client *client, | |||
1577 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1577 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1578 | 1578 | ||
1579 | s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE; | 1579 | s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE; |
1580 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 1580 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1581 | ret = media_entity_init(&sd->entity, 1, &s5k6aa->pad, 0); | 1581 | ret = media_entity_pads_init(&sd->entity, 1, &s5k6aa->pad); |
1582 | if (ret) | 1582 | if (ret) |
1583 | return ret; | 1583 | return ret; |
1584 | 1584 | ||
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index fb39dfd55e75..a215efe7a8ba 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c | |||
@@ -2487,31 +2487,31 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor) | |||
2487 | if (!last) | 2487 | if (!last) |
2488 | continue; | 2488 | continue; |
2489 | 2489 | ||
2490 | rval = media_entity_init(&this->sd.entity, | 2490 | rval = media_entity_pads_init(&this->sd.entity, |
2491 | this->npads, this->pads, 0); | 2491 | this->npads, this->pads); |
2492 | if (rval) { | 2492 | if (rval) { |
2493 | dev_err(&client->dev, | 2493 | dev_err(&client->dev, |
2494 | "media_entity_init failed\n"); | 2494 | "media_entity_pads_init failed\n"); |
2495 | return rval; | 2495 | return rval; |
2496 | } | 2496 | } |
2497 | 2497 | ||
2498 | rval = media_entity_create_link(&this->sd.entity, | 2498 | rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, |
2499 | this->source_pad, | 2499 | &this->sd); |
2500 | &last->sd.entity, | ||
2501 | last->sink_pad, | ||
2502 | MEDIA_LNK_FL_ENABLED | | ||
2503 | MEDIA_LNK_FL_IMMUTABLE); | ||
2504 | if (rval) { | 2500 | if (rval) { |
2505 | dev_err(&client->dev, | 2501 | dev_err(&client->dev, |
2506 | "media_entity_create_link failed\n"); | 2502 | "v4l2_device_register_subdev failed\n"); |
2507 | return rval; | 2503 | return rval; |
2508 | } | 2504 | } |
2509 | 2505 | ||
2510 | rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, | 2506 | rval = media_create_pad_link(&this->sd.entity, |
2511 | &this->sd); | 2507 | this->source_pad, |
2508 | &last->sd.entity, | ||
2509 | last->sink_pad, | ||
2510 | MEDIA_LNK_FL_ENABLED | | ||
2511 | MEDIA_LNK_FL_IMMUTABLE); | ||
2512 | if (rval) { | 2512 | if (rval) { |
2513 | dev_err(&client->dev, | 2513 | dev_err(&client->dev, |
2514 | "v4l2_device_register_subdev failed\n"); | 2514 | "media_create_pad_link failed\n"); |
2515 | return rval; | 2515 | return rval; |
2516 | } | 2516 | } |
2517 | } | 2517 | } |
@@ -2763,7 +2763,7 @@ static int smiapp_init(struct smiapp_sensor *sensor) | |||
2763 | 2763 | ||
2764 | dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile); | 2764 | dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile); |
2765 | 2765 | ||
2766 | sensor->pixel_array->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 2766 | sensor->pixel_array->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
2767 | 2767 | ||
2768 | /* final steps */ | 2768 | /* final steps */ |
2769 | smiapp_read_frame_fmt(sensor); | 2769 | smiapp_read_frame_fmt(sensor); |
@@ -3077,8 +3077,8 @@ static int smiapp_probe(struct i2c_client *client, | |||
3077 | sensor->src->sensor = sensor; | 3077 | sensor->src->sensor = sensor; |
3078 | 3078 | ||
3079 | sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE; | 3079 | sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE; |
3080 | rval = media_entity_init(&sensor->src->sd.entity, 2, | 3080 | rval = media_entity_pads_init(&sensor->src->sd.entity, 2, |
3081 | sensor->src->pads, 0); | 3081 | sensor->src->pads); |
3082 | if (rval < 0) | 3082 | if (rval < 0) |
3083 | return rval; | 3083 | return rval; |
3084 | 3084 | ||
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 77b801152ea5..3397eb99c67b 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c | |||
@@ -1889,7 +1889,7 @@ static int tc358743_probe(struct i2c_client *client, | |||
1889 | } | 1889 | } |
1890 | 1890 | ||
1891 | state->pad.flags = MEDIA_PAD_FL_SOURCE; | 1891 | state->pad.flags = MEDIA_PAD_FL_SOURCE; |
1892 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | 1892 | err = media_entity_pads_init(&sd->entity, 1, &state->pad); |
1893 | if (err < 0) | 1893 | if (err < 0) |
1894 | goto err_hdl; | 1894 | goto err_hdl; |
1895 | 1895 | ||
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index b5dba5b7ce3a..7fa5f1e4fe37 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c | |||
@@ -1095,9 +1095,9 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1095 | #if defined(CONFIG_MEDIA_CONTROLLER) | 1095 | #if defined(CONFIG_MEDIA_CONTROLLER) |
1096 | decoder->pad.flags = MEDIA_PAD_FL_SOURCE; | 1096 | decoder->pad.flags = MEDIA_PAD_FL_SOURCE; |
1097 | decoder->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1097 | decoder->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1098 | decoder->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; | 1098 | decoder->sd.entity.flags |= MEDIA_ENT_F_ATV_DECODER; |
1099 | 1099 | ||
1100 | ret = media_entity_init(&decoder->sd.entity, 1, &decoder->pad, 0); | 1100 | ret = media_entity_pads_init(&decoder->sd.entity, 1, &decoder->pad); |
1101 | if (ret < 0) { | 1101 | if (ret < 0) { |
1102 | v4l2_err(sd, "%s decoder driver failed to register !!\n", | 1102 | v4l2_err(sd, "%s decoder driver failed to register !!\n", |
1103 | sd->name); | 1103 | sd->name); |
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 772a3043ae3b..83c79fa5f61d 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c | |||
@@ -1012,9 +1012,9 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) | |||
1012 | #if defined(CONFIG_MEDIA_CONTROLLER) | 1012 | #if defined(CONFIG_MEDIA_CONTROLLER) |
1013 | device->pad.flags = MEDIA_PAD_FL_SOURCE; | 1013 | device->pad.flags = MEDIA_PAD_FL_SOURCE; |
1014 | device->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1014 | device->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1015 | device->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; | 1015 | device->sd.entity.flags |= MEDIA_ENT_F_ATV_DECODER; |
1016 | 1016 | ||
1017 | error = media_entity_init(&device->sd.entity, 1, &device->pad, 0); | 1017 | error = media_entity_pads_init(&device->sd.entity, 1, &device->pad); |
1018 | if (error < 0) | 1018 | if (error < 0) |
1019 | return error; | 1019 | return error; |
1020 | #endif | 1020 | #endif |
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 7b39440192d6..7dae0ac0f3ae 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c | |||
@@ -22,14 +22,18 @@ | |||
22 | 22 | ||
23 | #include <linux/compat.h> | 23 | #include <linux/compat.h> |
24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
25 | #include <linux/idr.h> | ||
25 | #include <linux/ioctl.h> | 26 | #include <linux/ioctl.h> |
26 | #include <linux/media.h> | 27 | #include <linux/media.h> |
28 | #include <linux/slab.h> | ||
27 | #include <linux/types.h> | 29 | #include <linux/types.h> |
28 | 30 | ||
29 | #include <media/media-device.h> | 31 | #include <media/media-device.h> |
30 | #include <media/media-devnode.h> | 32 | #include <media/media-devnode.h> |
31 | #include <media/media-entity.h> | 33 | #include <media/media-entity.h> |
32 | 34 | ||
35 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
36 | |||
33 | /* ----------------------------------------------------------------------------- | 37 | /* ----------------------------------------------------------------------------- |
34 | * Userspace API | 38 | * Userspace API |
35 | */ | 39 | */ |
@@ -75,8 +79,8 @@ static struct media_entity *find_entity(struct media_device *mdev, u32 id) | |||
75 | spin_lock(&mdev->lock); | 79 | spin_lock(&mdev->lock); |
76 | 80 | ||
77 | media_device_for_each_entity(entity, mdev) { | 81 | media_device_for_each_entity(entity, mdev) { |
78 | if ((entity->id == id && !next) || | 82 | if (((media_entity_id(entity) == id) && !next) || |
79 | (entity->id > id && next)) { | 83 | ((media_entity_id(entity) > id) && next)) { |
80 | spin_unlock(&mdev->lock); | 84 | spin_unlock(&mdev->lock); |
81 | return entity; | 85 | return entity; |
82 | } | 86 | } |
@@ -102,13 +106,13 @@ static long media_device_enum_entities(struct media_device *mdev, | |||
102 | if (ent == NULL) | 106 | if (ent == NULL) |
103 | return -EINVAL; | 107 | return -EINVAL; |
104 | 108 | ||
105 | u_ent.id = ent->id; | 109 | u_ent.id = media_entity_id(ent); |
106 | if (ent->name) | 110 | if (ent->name) |
107 | strlcpy(u_ent.name, ent->name, sizeof(u_ent.name)); | 111 | strlcpy(u_ent.name, ent->name, sizeof(u_ent.name)); |
108 | u_ent.type = ent->type; | 112 | u_ent.type = ent->function; |
109 | u_ent.revision = ent->revision; | 113 | u_ent.revision = 0; /* Unused */ |
110 | u_ent.flags = ent->flags; | 114 | u_ent.flags = ent->flags; |
111 | u_ent.group_id = ent->group_id; | 115 | u_ent.group_id = 0; /* Unused */ |
112 | u_ent.pads = ent->num_pads; | 116 | u_ent.pads = ent->num_pads; |
113 | u_ent.links = ent->num_links - ent->num_backlinks; | 117 | u_ent.links = ent->num_links - ent->num_backlinks; |
114 | memcpy(&u_ent.raw, &ent->info, sizeof(ent->info)); | 118 | memcpy(&u_ent.raw, &ent->info, sizeof(ent->info)); |
@@ -120,7 +124,7 @@ static long media_device_enum_entities(struct media_device *mdev, | |||
120 | static void media_device_kpad_to_upad(const struct media_pad *kpad, | 124 | static void media_device_kpad_to_upad(const struct media_pad *kpad, |
121 | struct media_pad_desc *upad) | 125 | struct media_pad_desc *upad) |
122 | { | 126 | { |
123 | upad->entity = kpad->entity->id; | 127 | upad->entity = media_entity_id(kpad->entity); |
124 | upad->index = kpad->index; | 128 | upad->index = kpad->index; |
125 | upad->flags = kpad->flags; | 129 | upad->flags = kpad->flags; |
126 | } | 130 | } |
@@ -148,25 +152,25 @@ static long __media_device_enum_links(struct media_device *mdev, | |||
148 | } | 152 | } |
149 | 153 | ||
150 | if (links->links) { | 154 | if (links->links) { |
151 | struct media_link_desc __user *ulink; | 155 | struct media_link *link; |
152 | unsigned int l; | 156 | struct media_link_desc __user *ulink_desc = links->links; |
153 | 157 | ||
154 | for (l = 0, ulink = links->links; l < entity->num_links; l++) { | 158 | list_for_each_entry(link, &entity->links, list) { |
155 | struct media_link_desc link; | 159 | struct media_link_desc klink_desc; |
156 | 160 | ||
157 | /* Ignore backlinks. */ | 161 | /* Ignore backlinks. */ |
158 | if (entity->links[l].source->entity != entity) | 162 | if (link->source->entity != entity) |
159 | continue; | 163 | continue; |
160 | 164 | memset(&klink_desc, 0, sizeof(klink_desc)); | |
161 | memset(&link, 0, sizeof(link)); | 165 | media_device_kpad_to_upad(link->source, |
162 | media_device_kpad_to_upad(entity->links[l].source, | 166 | &klink_desc.source); |
163 | &link.source); | 167 | media_device_kpad_to_upad(link->sink, |
164 | media_device_kpad_to_upad(entity->links[l].sink, | 168 | &klink_desc.sink); |
165 | &link.sink); | 169 | klink_desc.flags = link->flags; |
166 | link.flags = entity->links[l].flags; | 170 | if (copy_to_user(ulink_desc, &klink_desc, |
167 | if (copy_to_user(ulink, &link, sizeof(*ulink))) | 171 | sizeof(*ulink_desc))) |
168 | return -EFAULT; | 172 | return -EFAULT; |
169 | ulink++; | 173 | ulink_desc++; |
170 | } | 174 | } |
171 | } | 175 | } |
172 | 176 | ||
@@ -230,6 +234,164 @@ static long media_device_setup_link(struct media_device *mdev, | |||
230 | return ret; | 234 | return ret; |
231 | } | 235 | } |
232 | 236 | ||
237 | #if 0 /* Let's postpone it to Kernel 4.6 */ | ||
238 | static long __media_device_get_topology(struct media_device *mdev, | ||
239 | struct media_v2_topology *topo) | ||
240 | { | ||
241 | struct media_entity *entity; | ||
242 | struct media_interface *intf; | ||
243 | struct media_pad *pad; | ||
244 | struct media_link *link; | ||
245 | struct media_v2_entity kentity, *uentity; | ||
246 | struct media_v2_interface kintf, *uintf; | ||
247 | struct media_v2_pad kpad, *upad; | ||
248 | struct media_v2_link klink, *ulink; | ||
249 | unsigned int i; | ||
250 | int ret = 0; | ||
251 | |||
252 | topo->topology_version = mdev->topology_version; | ||
253 | |||
254 | /* Get entities and number of entities */ | ||
255 | i = 0; | ||
256 | uentity = media_get_uptr(topo->ptr_entities); | ||
257 | media_device_for_each_entity(entity, mdev) { | ||
258 | i++; | ||
259 | if (ret || !uentity) | ||
260 | continue; | ||
261 | |||
262 | if (i > topo->num_entities) { | ||
263 | ret = -ENOSPC; | ||
264 | continue; | ||
265 | } | ||
266 | |||
267 | /* Copy fields to userspace struct if not error */ | ||
268 | memset(&kentity, 0, sizeof(kentity)); | ||
269 | kentity.id = entity->graph_obj.id; | ||
270 | kentity.function = entity->function; | ||
271 | strncpy(kentity.name, entity->name, | ||
272 | sizeof(kentity.name)); | ||
273 | |||
274 | if (copy_to_user(uentity, &kentity, sizeof(kentity))) | ||
275 | ret = -EFAULT; | ||
276 | uentity++; | ||
277 | } | ||
278 | topo->num_entities = i; | ||
279 | |||
280 | /* Get interfaces and number of interfaces */ | ||
281 | i = 0; | ||
282 | uintf = media_get_uptr(topo->ptr_interfaces); | ||
283 | media_device_for_each_intf(intf, mdev) { | ||
284 | i++; | ||
285 | if (ret || !uintf) | ||
286 | continue; | ||
287 | |||
288 | if (i > topo->num_interfaces) { | ||
289 | ret = -ENOSPC; | ||
290 | continue; | ||
291 | } | ||
292 | |||
293 | memset(&kintf, 0, sizeof(kintf)); | ||
294 | |||
295 | /* Copy intf fields to userspace struct */ | ||
296 | kintf.id = intf->graph_obj.id; | ||
297 | kintf.intf_type = intf->type; | ||
298 | kintf.flags = intf->flags; | ||
299 | |||
300 | if (media_type(&intf->graph_obj) == MEDIA_GRAPH_INTF_DEVNODE) { | ||
301 | struct media_intf_devnode *devnode; | ||
302 | |||
303 | devnode = intf_to_devnode(intf); | ||
304 | |||
305 | kintf.devnode.major = devnode->major; | ||
306 | kintf.devnode.minor = devnode->minor; | ||
307 | } | ||
308 | |||
309 | if (copy_to_user(uintf, &kintf, sizeof(kintf))) | ||
310 | ret = -EFAULT; | ||
311 | uintf++; | ||
312 | } | ||
313 | topo->num_interfaces = i; | ||
314 | |||
315 | /* Get pads and number of pads */ | ||
316 | i = 0; | ||
317 | upad = media_get_uptr(topo->ptr_pads); | ||
318 | media_device_for_each_pad(pad, mdev) { | ||
319 | i++; | ||
320 | if (ret || !upad) | ||
321 | continue; | ||
322 | |||
323 | if (i > topo->num_pads) { | ||
324 | ret = -ENOSPC; | ||
325 | continue; | ||
326 | } | ||
327 | |||
328 | memset(&kpad, 0, sizeof(kpad)); | ||
329 | |||
330 | /* Copy pad fields to userspace struct */ | ||
331 | kpad.id = pad->graph_obj.id; | ||
332 | kpad.entity_id = pad->entity->graph_obj.id; | ||
333 | kpad.flags = pad->flags; | ||
334 | |||
335 | if (copy_to_user(upad, &kpad, sizeof(kpad))) | ||
336 | ret = -EFAULT; | ||
337 | upad++; | ||
338 | } | ||
339 | topo->num_pads = i; | ||
340 | |||
341 | /* Get links and number of links */ | ||
342 | i = 0; | ||
343 | ulink = media_get_uptr(topo->ptr_links); | ||
344 | media_device_for_each_link(link, mdev) { | ||
345 | if (link->is_backlink) | ||
346 | continue; | ||
347 | |||
348 | i++; | ||
349 | |||
350 | if (ret || !ulink) | ||
351 | continue; | ||
352 | |||
353 | if (i > topo->num_links) { | ||
354 | ret = -ENOSPC; | ||
355 | continue; | ||
356 | } | ||
357 | |||
358 | memset(&klink, 0, sizeof(klink)); | ||
359 | |||
360 | /* Copy link fields to userspace struct */ | ||
361 | klink.id = link->graph_obj.id; | ||
362 | klink.source_id = link->gobj0->id; | ||
363 | klink.sink_id = link->gobj1->id; | ||
364 | klink.flags = link->flags; | ||
365 | |||
366 | if (copy_to_user(ulink, &klink, sizeof(klink))) | ||
367 | ret = -EFAULT; | ||
368 | ulink++; | ||
369 | } | ||
370 | topo->num_links = i; | ||
371 | |||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static long media_device_get_topology(struct media_device *mdev, | ||
376 | struct media_v2_topology __user *utopo) | ||
377 | { | ||
378 | struct media_v2_topology ktopo; | ||
379 | int ret; | ||
380 | |||
381 | if (copy_from_user(&ktopo, utopo, sizeof(ktopo))) | ||
382 | return -EFAULT; | ||
383 | |||
384 | ret = __media_device_get_topology(mdev, &ktopo); | ||
385 | if (ret < 0) | ||
386 | return ret; | ||
387 | |||
388 | if (copy_to_user(utopo, &ktopo, sizeof(*utopo))) | ||
389 | return -EFAULT; | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | #endif | ||
394 | |||
233 | static long media_device_ioctl(struct file *filp, unsigned int cmd, | 395 | static long media_device_ioctl(struct file *filp, unsigned int cmd, |
234 | unsigned long arg) | 396 | unsigned long arg) |
235 | { | 397 | { |
@@ -262,6 +424,14 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd, | |||
262 | mutex_unlock(&dev->graph_mutex); | 424 | mutex_unlock(&dev->graph_mutex); |
263 | break; | 425 | break; |
264 | 426 | ||
427 | #if 0 /* Let's postpone it to Kernel 4.6 */ | ||
428 | case MEDIA_IOC_G_TOPOLOGY: | ||
429 | mutex_lock(&dev->graph_mutex); | ||
430 | ret = media_device_get_topology(dev, | ||
431 | (struct media_v2_topology __user *)arg); | ||
432 | mutex_unlock(&dev->graph_mutex); | ||
433 | break; | ||
434 | #endif | ||
265 | default: | 435 | default: |
266 | ret = -ENOIOCTLCMD; | 436 | ret = -ENOIOCTLCMD; |
267 | } | 437 | } |
@@ -310,6 +480,9 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd, | |||
310 | case MEDIA_IOC_DEVICE_INFO: | 480 | case MEDIA_IOC_DEVICE_INFO: |
311 | case MEDIA_IOC_ENUM_ENTITIES: | 481 | case MEDIA_IOC_ENUM_ENTITIES: |
312 | case MEDIA_IOC_SETUP_LINK: | 482 | case MEDIA_IOC_SETUP_LINK: |
483 | #if 0 /* Let's postpone it to Kernel 4.6 */ | ||
484 | case MEDIA_IOC_G_TOPOLOGY: | ||
485 | #endif | ||
313 | return media_device_ioctl(filp, cmd, arg); | 486 | return media_device_ioctl(filp, cmd, arg); |
314 | 487 | ||
315 | case MEDIA_IOC_ENUM_LINKS32: | 488 | case MEDIA_IOC_ENUM_LINKS32: |
@@ -357,10 +530,107 @@ static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); | |||
357 | 530 | ||
358 | static void media_device_release(struct media_devnode *mdev) | 531 | static void media_device_release(struct media_devnode *mdev) |
359 | { | 532 | { |
533 | dev_dbg(mdev->parent, "Media device released\n"); | ||
534 | } | ||
535 | |||
536 | /** | ||
537 | * media_device_register_entity - Register an entity with a media device | ||
538 | * @mdev: The media device | ||
539 | * @entity: The entity | ||
540 | */ | ||
541 | int __must_check media_device_register_entity(struct media_device *mdev, | ||
542 | struct media_entity *entity) | ||
543 | { | ||
544 | unsigned int i; | ||
545 | int ret; | ||
546 | |||
547 | if (entity->function == MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN || | ||
548 | entity->function == MEDIA_ENT_F_UNKNOWN) | ||
549 | dev_warn(mdev->dev, | ||
550 | "Entity type for entity %s was not initialized!\n", | ||
551 | entity->name); | ||
552 | |||
553 | /* Warn if we apparently re-register an entity */ | ||
554 | WARN_ON(entity->graph_obj.mdev != NULL); | ||
555 | entity->graph_obj.mdev = mdev; | ||
556 | INIT_LIST_HEAD(&entity->links); | ||
557 | entity->num_links = 0; | ||
558 | entity->num_backlinks = 0; | ||
559 | |||
560 | if (!ida_pre_get(&mdev->entity_internal_idx, GFP_KERNEL)) | ||
561 | return -ENOMEM; | ||
562 | |||
563 | spin_lock(&mdev->lock); | ||
564 | |||
565 | ret = ida_get_new_above(&mdev->entity_internal_idx, 1, | ||
566 | &entity->internal_idx); | ||
567 | if (ret < 0) { | ||
568 | spin_unlock(&mdev->lock); | ||
569 | return ret; | ||
570 | } | ||
571 | |||
572 | mdev->entity_internal_idx_max = | ||
573 | max(mdev->entity_internal_idx_max, entity->internal_idx); | ||
574 | |||
575 | /* Initialize media_gobj embedded at the entity */ | ||
576 | media_gobj_create(mdev, MEDIA_GRAPH_ENTITY, &entity->graph_obj); | ||
577 | |||
578 | /* Initialize objects at the pads */ | ||
579 | for (i = 0; i < entity->num_pads; i++) | ||
580 | media_gobj_create(mdev, MEDIA_GRAPH_PAD, | ||
581 | &entity->pads[i].graph_obj); | ||
582 | |||
583 | spin_unlock(&mdev->lock); | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | EXPORT_SYMBOL_GPL(media_device_register_entity); | ||
588 | |||
589 | static void __media_device_unregister_entity(struct media_entity *entity) | ||
590 | { | ||
591 | struct media_device *mdev = entity->graph_obj.mdev; | ||
592 | struct media_link *link, *tmp; | ||
593 | struct media_interface *intf; | ||
594 | unsigned int i; | ||
595 | |||
596 | ida_simple_remove(&mdev->entity_internal_idx, entity->internal_idx); | ||
597 | |||
598 | /* Remove all interface links pointing to this entity */ | ||
599 | list_for_each_entry(intf, &mdev->interfaces, graph_obj.list) { | ||
600 | list_for_each_entry_safe(link, tmp, &intf->links, list) { | ||
601 | if (link->entity == entity) | ||
602 | __media_remove_intf_link(link); | ||
603 | } | ||
604 | } | ||
605 | |||
606 | /* Remove all data links that belong to this entity */ | ||
607 | __media_entity_remove_links(entity); | ||
608 | |||
609 | /* Remove all pads that belong to this entity */ | ||
610 | for (i = 0; i < entity->num_pads; i++) | ||
611 | media_gobj_destroy(&entity->pads[i].graph_obj); | ||
612 | |||
613 | /* Remove the entity */ | ||
614 | media_gobj_destroy(&entity->graph_obj); | ||
615 | |||
616 | entity->graph_obj.mdev = NULL; | ||
360 | } | 617 | } |
361 | 618 | ||
619 | void media_device_unregister_entity(struct media_entity *entity) | ||
620 | { | ||
621 | struct media_device *mdev = entity->graph_obj.mdev; | ||
622 | |||
623 | if (mdev == NULL) | ||
624 | return; | ||
625 | |||
626 | spin_lock(&mdev->lock); | ||
627 | __media_device_unregister_entity(entity); | ||
628 | spin_unlock(&mdev->lock); | ||
629 | } | ||
630 | EXPORT_SYMBOL_GPL(media_device_unregister_entity); | ||
631 | |||
362 | /** | 632 | /** |
363 | * media_device_register - register a media device | 633 | * media_device_init() - initialize a media device |
364 | * @mdev: The media device | 634 | * @mdev: The media device |
365 | * | 635 | * |
366 | * The caller is responsible for initializing the media device before | 636 | * The caller is responsible for initializing the media device before |
@@ -369,23 +639,41 @@ static void media_device_release(struct media_devnode *mdev) | |||
369 | * - dev must point to the parent device | 639 | * - dev must point to the parent device |
370 | * - model must be filled with the device model name | 640 | * - model must be filled with the device model name |
371 | */ | 641 | */ |
372 | int __must_check __media_device_register(struct media_device *mdev, | 642 | void media_device_init(struct media_device *mdev) |
373 | struct module *owner) | ||
374 | { | 643 | { |
375 | int ret; | ||
376 | |||
377 | if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0)) | ||
378 | return -EINVAL; | ||
379 | |||
380 | mdev->entity_id = 1; | ||
381 | INIT_LIST_HEAD(&mdev->entities); | 644 | INIT_LIST_HEAD(&mdev->entities); |
645 | INIT_LIST_HEAD(&mdev->interfaces); | ||
646 | INIT_LIST_HEAD(&mdev->pads); | ||
647 | INIT_LIST_HEAD(&mdev->links); | ||
382 | spin_lock_init(&mdev->lock); | 648 | spin_lock_init(&mdev->lock); |
383 | mutex_init(&mdev->graph_mutex); | 649 | mutex_init(&mdev->graph_mutex); |
650 | ida_init(&mdev->entity_internal_idx); | ||
651 | |||
652 | dev_dbg(mdev->dev, "Media device initialized\n"); | ||
653 | } | ||
654 | EXPORT_SYMBOL_GPL(media_device_init); | ||
655 | |||
656 | void media_device_cleanup(struct media_device *mdev) | ||
657 | { | ||
658 | ida_destroy(&mdev->entity_internal_idx); | ||
659 | mdev->entity_internal_idx_max = 0; | ||
660 | mutex_destroy(&mdev->graph_mutex); | ||
661 | } | ||
662 | EXPORT_SYMBOL_GPL(media_device_cleanup); | ||
663 | |||
664 | int __must_check __media_device_register(struct media_device *mdev, | ||
665 | struct module *owner) | ||
666 | { | ||
667 | int ret; | ||
384 | 668 | ||
385 | /* Register the device node. */ | 669 | /* Register the device node. */ |
386 | mdev->devnode.fops = &media_device_fops; | 670 | mdev->devnode.fops = &media_device_fops; |
387 | mdev->devnode.parent = mdev->dev; | 671 | mdev->devnode.parent = mdev->dev; |
388 | mdev->devnode.release = media_device_release; | 672 | mdev->devnode.release = media_device_release; |
673 | |||
674 | /* Set version 0 to indicate user-space that the graph is static */ | ||
675 | mdev->topology_version = 0; | ||
676 | |||
389 | ret = media_devnode_register(&mdev->devnode, owner); | 677 | ret = media_devnode_register(&mdev->devnode, owner); |
390 | if (ret < 0) | 678 | if (ret < 0) |
391 | return ret; | 679 | return ret; |
@@ -396,69 +684,74 @@ int __must_check __media_device_register(struct media_device *mdev, | |||
396 | return ret; | 684 | return ret; |
397 | } | 685 | } |
398 | 686 | ||
687 | dev_dbg(mdev->dev, "Media device registered\n"); | ||
688 | |||
399 | return 0; | 689 | return 0; |
400 | } | 690 | } |
401 | EXPORT_SYMBOL_GPL(__media_device_register); | 691 | EXPORT_SYMBOL_GPL(__media_device_register); |
402 | 692 | ||
403 | /** | ||
404 | * media_device_unregister - unregister a media device | ||
405 | * @mdev: The media device | ||
406 | * | ||
407 | */ | ||
408 | void media_device_unregister(struct media_device *mdev) | 693 | void media_device_unregister(struct media_device *mdev) |
409 | { | 694 | { |
410 | struct media_entity *entity; | 695 | struct media_entity *entity; |
411 | struct media_entity *next; | 696 | struct media_entity *next; |
697 | struct media_interface *intf, *tmp_intf; | ||
412 | 698 | ||
413 | list_for_each_entry_safe(entity, next, &mdev->entities, list) | 699 | if (mdev == NULL) |
414 | media_device_unregister_entity(entity); | 700 | return; |
701 | |||
702 | spin_lock(&mdev->lock); | ||
703 | |||
704 | /* Check if mdev was ever registered at all */ | ||
705 | if (!media_devnode_is_registered(&mdev->devnode)) { | ||
706 | spin_unlock(&mdev->lock); | ||
707 | return; | ||
708 | } | ||
709 | |||
710 | /* Remove all entities from the media device */ | ||
711 | list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list) | ||
712 | __media_device_unregister_entity(entity); | ||
713 | |||
714 | /* Remove all interfaces from the media device */ | ||
715 | list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces, | ||
716 | graph_obj.list) { | ||
717 | __media_remove_intf_links(intf); | ||
718 | media_gobj_destroy(&intf->graph_obj); | ||
719 | kfree(intf); | ||
720 | } | ||
721 | |||
722 | spin_unlock(&mdev->lock); | ||
415 | 723 | ||
416 | device_remove_file(&mdev->devnode.dev, &dev_attr_model); | 724 | device_remove_file(&mdev->devnode.dev, &dev_attr_model); |
417 | media_devnode_unregister(&mdev->devnode); | 725 | media_devnode_unregister(&mdev->devnode); |
726 | |||
727 | dev_dbg(mdev->dev, "Media device unregistered\n"); | ||
418 | } | 728 | } |
419 | EXPORT_SYMBOL_GPL(media_device_unregister); | 729 | EXPORT_SYMBOL_GPL(media_device_unregister); |
420 | 730 | ||
421 | /** | 731 | static void media_device_release_devres(struct device *dev, void *res) |
422 | * media_device_register_entity - Register an entity with a media device | ||
423 | * @mdev: The media device | ||
424 | * @entity: The entity | ||
425 | */ | ||
426 | int __must_check media_device_register_entity(struct media_device *mdev, | ||
427 | struct media_entity *entity) | ||
428 | { | 732 | { |
429 | /* Warn if we apparently re-register an entity */ | ||
430 | WARN_ON(entity->parent != NULL); | ||
431 | entity->parent = mdev; | ||
432 | |||
433 | spin_lock(&mdev->lock); | ||
434 | if (entity->id == 0) | ||
435 | entity->id = mdev->entity_id++; | ||
436 | else | ||
437 | mdev->entity_id = max(entity->id + 1, mdev->entity_id); | ||
438 | list_add_tail(&entity->list, &mdev->entities); | ||
439 | spin_unlock(&mdev->lock); | ||
440 | |||
441 | return 0; | ||
442 | } | 733 | } |
443 | EXPORT_SYMBOL_GPL(media_device_register_entity); | ||
444 | 734 | ||
445 | /** | 735 | struct media_device *media_device_get_devres(struct device *dev) |
446 | * media_device_unregister_entity - Unregister an entity | ||
447 | * @entity: The entity | ||
448 | * | ||
449 | * If the entity has never been registered this function will return | ||
450 | * immediately. | ||
451 | */ | ||
452 | void media_device_unregister_entity(struct media_entity *entity) | ||
453 | { | 736 | { |
454 | struct media_device *mdev = entity->parent; | 737 | struct media_device *mdev; |
455 | 738 | ||
456 | if (mdev == NULL) | 739 | mdev = devres_find(dev, media_device_release_devres, NULL, NULL); |
457 | return; | 740 | if (mdev) |
741 | return mdev; | ||
458 | 742 | ||
459 | spin_lock(&mdev->lock); | 743 | mdev = devres_alloc(media_device_release_devres, |
460 | list_del(&entity->list); | 744 | sizeof(struct media_device), GFP_KERNEL); |
461 | spin_unlock(&mdev->lock); | 745 | if (!mdev) |
462 | entity->parent = NULL; | 746 | return NULL; |
747 | return devres_get(dev, mdev, NULL, NULL); | ||
463 | } | 748 | } |
464 | EXPORT_SYMBOL_GPL(media_device_unregister_entity); | 749 | EXPORT_SYMBOL_GPL(media_device_get_devres); |
750 | |||
751 | struct media_device *media_device_find_devres(struct device *dev) | ||
752 | { | ||
753 | return devres_find(dev, media_device_release_devres, NULL, NULL); | ||
754 | } | ||
755 | EXPORT_SYMBOL_GPL(media_device_find_devres); | ||
756 | |||
757 | #endif /* CONFIG_MEDIA_CONTROLLER */ | ||
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index ebf9626e5ae5..cea35bf20011 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c | |||
@@ -217,20 +217,6 @@ static const struct file_operations media_devnode_fops = { | |||
217 | .llseek = no_llseek, | 217 | .llseek = no_llseek, |
218 | }; | 218 | }; |
219 | 219 | ||
220 | /** | ||
221 | * media_devnode_register - register a media device node | ||
222 | * @mdev: media device node structure we want to register | ||
223 | * | ||
224 | * The registration code assigns minor numbers and registers the new device node | ||
225 | * with the kernel. An error is returned if no free minor number can be found, | ||
226 | * or if the registration of the device node fails. | ||
227 | * | ||
228 | * Zero is returned on success. | ||
229 | * | ||
230 | * Note that if the media_devnode_register call fails, the release() callback of | ||
231 | * the media_devnode structure is *not* called, so the caller is responsible for | ||
232 | * freeing any data. | ||
233 | */ | ||
234 | int __must_check media_devnode_register(struct media_devnode *mdev, | 220 | int __must_check media_devnode_register(struct media_devnode *mdev, |
235 | struct module *owner) | 221 | struct module *owner) |
236 | { | 222 | { |
@@ -285,16 +271,6 @@ error: | |||
285 | return ret; | 271 | return ret; |
286 | } | 272 | } |
287 | 273 | ||
288 | /** | ||
289 | * media_devnode_unregister - unregister a media device node | ||
290 | * @mdev: the device node to unregister | ||
291 | * | ||
292 | * This unregisters the passed device. Future open calls will be met with | ||
293 | * errors. | ||
294 | * | ||
295 | * This function can safely be called if the device node has never been | ||
296 | * registered or has already been unregistered. | ||
297 | */ | ||
298 | void media_devnode_unregister(struct media_devnode *mdev) | 274 | void media_devnode_unregister(struct media_devnode *mdev) |
299 | { | 275 | { |
300 | /* Check if mdev was ever registered at all */ | 276 | /* Check if mdev was ever registered at all */ |
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 767fe55ba08e..e89d85a7d31b 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c | |||
@@ -26,65 +26,198 @@ | |||
26 | #include <media/media-entity.h> | 26 | #include <media/media-entity.h> |
27 | #include <media/media-device.h> | 27 | #include <media/media-device.h> |
28 | 28 | ||
29 | static inline const char *gobj_type(enum media_gobj_type type) | ||
30 | { | ||
31 | switch (type) { | ||
32 | case MEDIA_GRAPH_ENTITY: | ||
33 | return "entity"; | ||
34 | case MEDIA_GRAPH_PAD: | ||
35 | return "pad"; | ||
36 | case MEDIA_GRAPH_LINK: | ||
37 | return "link"; | ||
38 | case MEDIA_GRAPH_INTF_DEVNODE: | ||
39 | return "intf-devnode"; | ||
40 | default: | ||
41 | return "unknown"; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | static inline const char *intf_type(struct media_interface *intf) | ||
46 | { | ||
47 | switch (intf->type) { | ||
48 | case MEDIA_INTF_T_DVB_FE: | ||
49 | return "frontend"; | ||
50 | case MEDIA_INTF_T_DVB_DEMUX: | ||
51 | return "demux"; | ||
52 | case MEDIA_INTF_T_DVB_DVR: | ||
53 | return "DVR"; | ||
54 | case MEDIA_INTF_T_DVB_CA: | ||
55 | return "CA"; | ||
56 | case MEDIA_INTF_T_DVB_NET: | ||
57 | return "dvbnet"; | ||
58 | case MEDIA_INTF_T_V4L_VIDEO: | ||
59 | return "video"; | ||
60 | case MEDIA_INTF_T_V4L_VBI: | ||
61 | return "vbi"; | ||
62 | case MEDIA_INTF_T_V4L_RADIO: | ||
63 | return "radio"; | ||
64 | case MEDIA_INTF_T_V4L_SUBDEV: | ||
65 | return "v4l2-subdev"; | ||
66 | case MEDIA_INTF_T_V4L_SWRADIO: | ||
67 | return "swradio"; | ||
68 | default: | ||
69 | return "unknown-intf"; | ||
70 | } | ||
71 | }; | ||
72 | |||
73 | __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum, | ||
74 | int idx_max) | ||
75 | { | ||
76 | ent_enum->bmap = kcalloc(DIV_ROUND_UP(idx_max, BITS_PER_LONG), | ||
77 | sizeof(long), GFP_KERNEL); | ||
78 | if (!ent_enum->bmap) | ||
79 | return -ENOMEM; | ||
80 | |||
81 | bitmap_zero(ent_enum->bmap, idx_max); | ||
82 | ent_enum->idx_max = idx_max; | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | EXPORT_SYMBOL_GPL(__media_entity_enum_init); | ||
87 | |||
88 | void media_entity_enum_cleanup(struct media_entity_enum *ent_enum) | ||
89 | { | ||
90 | kfree(ent_enum->bmap); | ||
91 | } | ||
92 | EXPORT_SYMBOL_GPL(media_entity_enum_cleanup); | ||
93 | |||
29 | /** | 94 | /** |
30 | * media_entity_init - Initialize a media entity | 95 | * dev_dbg_obj - Prints in debug mode a change on some object |
31 | * | ||
32 | * @num_pads: Total number of sink and source pads. | ||
33 | * @extra_links: Initial estimate of the number of extra links. | ||
34 | * @pads: Array of 'num_pads' pads. | ||
35 | * | ||
36 | * The total number of pads is an intrinsic property of entities known by the | ||
37 | * entity driver, while the total number of links depends on hardware design | ||
38 | * and is an extrinsic property unknown to the entity driver. However, in most | ||
39 | * use cases the entity driver can guess the number of links which can safely | ||
40 | * be assumed to be equal to or larger than the number of pads. | ||
41 | * | ||
42 | * For those reasons the links array can be preallocated based on the entity | ||
43 | * driver guess and will be reallocated later if extra links need to be | ||
44 | * created. | ||
45 | * | 96 | * |
46 | * This function allocates a links array with enough space to hold at least | 97 | * @event_name: Name of the event to report. Could be __func__ |
47 | * 'num_pads' + 'extra_links' elements. The media_entity::max_links field will | 98 | * @gobj: Pointer to the object |
48 | * be set to the number of allocated elements. | ||
49 | * | 99 | * |
50 | * The pads array is managed by the entity driver and passed to | 100 | * Enabled only if DEBUG or CONFIG_DYNAMIC_DEBUG. Otherwise, it |
51 | * media_entity_init() where its pointer will be stored in the entity structure. | 101 | * won't produce any code. |
52 | */ | 102 | */ |
53 | int | 103 | static void dev_dbg_obj(const char *event_name, struct media_gobj *gobj) |
54 | media_entity_init(struct media_entity *entity, u16 num_pads, | ||
55 | struct media_pad *pads, u16 extra_links) | ||
56 | { | 104 | { |
57 | struct media_link *links; | 105 | #if defined(DEBUG) || defined (CONFIG_DYNAMIC_DEBUG) |
58 | unsigned int max_links = num_pads + extra_links; | 106 | switch (media_type(gobj)) { |
59 | unsigned int i; | 107 | case MEDIA_GRAPH_ENTITY: |
108 | dev_dbg(gobj->mdev->dev, | ||
109 | "%s id %u: entity '%s'\n", | ||
110 | event_name, media_id(gobj), | ||
111 | gobj_to_entity(gobj)->name); | ||
112 | break; | ||
113 | case MEDIA_GRAPH_LINK: | ||
114 | { | ||
115 | struct media_link *link = gobj_to_link(gobj); | ||
116 | |||
117 | dev_dbg(gobj->mdev->dev, | ||
118 | "%s id %u: %s link id %u ==> id %u\n", | ||
119 | event_name, media_id(gobj), | ||
120 | media_type(link->gobj0) == MEDIA_GRAPH_PAD ? | ||
121 | "data" : "interface", | ||
122 | media_id(link->gobj0), | ||
123 | media_id(link->gobj1)); | ||
124 | break; | ||
125 | } | ||
126 | case MEDIA_GRAPH_PAD: | ||
127 | { | ||
128 | struct media_pad *pad = gobj_to_pad(gobj); | ||
129 | |||
130 | dev_dbg(gobj->mdev->dev, | ||
131 | "%s id %u: %s%spad '%s':%d\n", | ||
132 | event_name, media_id(gobj), | ||
133 | pad->flags & MEDIA_PAD_FL_SINK ? "sink " : "", | ||
134 | pad->flags & MEDIA_PAD_FL_SOURCE ? "source " : "", | ||
135 | pad->entity->name, pad->index); | ||
136 | break; | ||
137 | } | ||
138 | case MEDIA_GRAPH_INTF_DEVNODE: | ||
139 | { | ||
140 | struct media_interface *intf = gobj_to_intf(gobj); | ||
141 | struct media_intf_devnode *devnode = intf_to_devnode(intf); | ||
142 | |||
143 | dev_dbg(gobj->mdev->dev, | ||
144 | "%s id %u: intf_devnode %s - major: %d, minor: %d\n", | ||
145 | event_name, media_id(gobj), | ||
146 | intf_type(intf), | ||
147 | devnode->major, devnode->minor); | ||
148 | break; | ||
149 | } | ||
150 | } | ||
151 | #endif | ||
152 | } | ||
60 | 153 | ||
61 | links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL); | 154 | void media_gobj_create(struct media_device *mdev, |
62 | if (links == NULL) | 155 | enum media_gobj_type type, |
63 | return -ENOMEM; | 156 | struct media_gobj *gobj) |
157 | { | ||
158 | BUG_ON(!mdev); | ||
159 | |||
160 | gobj->mdev = mdev; | ||
161 | |||
162 | /* Create a per-type unique object ID */ | ||
163 | gobj->id = media_gobj_gen_id(type, ++mdev->id); | ||
164 | |||
165 | switch (type) { | ||
166 | case MEDIA_GRAPH_ENTITY: | ||
167 | list_add_tail(&gobj->list, &mdev->entities); | ||
168 | break; | ||
169 | case MEDIA_GRAPH_PAD: | ||
170 | list_add_tail(&gobj->list, &mdev->pads); | ||
171 | break; | ||
172 | case MEDIA_GRAPH_LINK: | ||
173 | list_add_tail(&gobj->list, &mdev->links); | ||
174 | break; | ||
175 | case MEDIA_GRAPH_INTF_DEVNODE: | ||
176 | list_add_tail(&gobj->list, &mdev->interfaces); | ||
177 | break; | ||
178 | } | ||
179 | |||
180 | mdev->topology_version++; | ||
181 | |||
182 | dev_dbg_obj(__func__, gobj); | ||
183 | } | ||
184 | |||
185 | void media_gobj_destroy(struct media_gobj *gobj) | ||
186 | { | ||
187 | dev_dbg_obj(__func__, gobj); | ||
188 | |||
189 | gobj->mdev->topology_version++; | ||
190 | |||
191 | /* Remove the object from mdev list */ | ||
192 | list_del(&gobj->list); | ||
193 | } | ||
194 | |||
195 | int media_entity_pads_init(struct media_entity *entity, u16 num_pads, | ||
196 | struct media_pad *pads) | ||
197 | { | ||
198 | struct media_device *mdev = entity->graph_obj.mdev; | ||
199 | unsigned int i; | ||
64 | 200 | ||
65 | entity->group_id = 0; | ||
66 | entity->max_links = max_links; | ||
67 | entity->num_links = 0; | ||
68 | entity->num_backlinks = 0; | ||
69 | entity->num_pads = num_pads; | 201 | entity->num_pads = num_pads; |
70 | entity->pads = pads; | 202 | entity->pads = pads; |
71 | entity->links = links; | 203 | |
204 | if (mdev) | ||
205 | spin_lock(&mdev->lock); | ||
72 | 206 | ||
73 | for (i = 0; i < num_pads; i++) { | 207 | for (i = 0; i < num_pads; i++) { |
74 | pads[i].entity = entity; | 208 | pads[i].entity = entity; |
75 | pads[i].index = i; | 209 | pads[i].index = i; |
210 | if (mdev) | ||
211 | media_gobj_create(mdev, MEDIA_GRAPH_PAD, | ||
212 | &entity->pads[i].graph_obj); | ||
76 | } | 213 | } |
77 | 214 | ||
78 | return 0; | 215 | if (mdev) |
79 | } | 216 | spin_unlock(&mdev->lock); |
80 | EXPORT_SYMBOL_GPL(media_entity_init); | ||
81 | 217 | ||
82 | void | 218 | return 0; |
83 | media_entity_cleanup(struct media_entity *entity) | ||
84 | { | ||
85 | kfree(entity->links); | ||
86 | } | 219 | } |
87 | EXPORT_SYMBOL_GPL(media_entity_cleanup); | 220 | EXPORT_SYMBOL_GPL(media_entity_pads_init); |
88 | 221 | ||
89 | /* ----------------------------------------------------------------------------- | 222 | /* ----------------------------------------------------------------------------- |
90 | * Graph traversal | 223 | * Graph traversal |
@@ -108,7 +241,7 @@ static void stack_push(struct media_entity_graph *graph, | |||
108 | return; | 241 | return; |
109 | } | 242 | } |
110 | graph->top++; | 243 | graph->top++; |
111 | graph->stack[graph->top].link = 0; | 244 | graph->stack[graph->top].link = entity->links.next; |
112 | graph->stack[graph->top].entity = entity; | 245 | graph->stack[graph->top].entity = entity; |
113 | } | 246 | } |
114 | 247 | ||
@@ -125,43 +258,51 @@ static struct media_entity *stack_pop(struct media_entity_graph *graph) | |||
125 | #define link_top(en) ((en)->stack[(en)->top].link) | 258 | #define link_top(en) ((en)->stack[(en)->top].link) |
126 | #define stack_top(en) ((en)->stack[(en)->top].entity) | 259 | #define stack_top(en) ((en)->stack[(en)->top].entity) |
127 | 260 | ||
261 | /* | ||
262 | * TODO: Get rid of this. | ||
263 | */ | ||
264 | #define MEDIA_ENTITY_MAX_PADS 512 | ||
265 | |||
128 | /** | 266 | /** |
129 | * media_entity_graph_walk_start - Start walking the media graph at a given entity | 267 | * media_entity_graph_walk_init - Allocate resources for graph walk |
130 | * @graph: Media graph structure that will be used to walk the graph | 268 | * @graph: Media graph structure that will be used to walk the graph |
131 | * @entity: Starting entity | 269 | * @mdev: Media device |
132 | * | 270 | * |
133 | * This function initializes the graph traversal structure to walk the entities | 271 | * Reserve resources for graph walk in media device's current |
134 | * graph starting at the given entity. The traversal structure must not be | 272 | * state. The memory must be released using |
135 | * modified by the caller during graph traversal. When done the structure can | 273 | * media_entity_graph_walk_free(). |
136 | * safely be freed. | 274 | * |
275 | * Returns error on failure, zero on success. | ||
137 | */ | 276 | */ |
277 | __must_check int media_entity_graph_walk_init( | ||
278 | struct media_entity_graph *graph, struct media_device *mdev) | ||
279 | { | ||
280 | return media_entity_enum_init(&graph->ent_enum, mdev); | ||
281 | } | ||
282 | EXPORT_SYMBOL_GPL(media_entity_graph_walk_init); | ||
283 | |||
284 | /** | ||
285 | * media_entity_graph_walk_cleanup - Release resources related to graph walking | ||
286 | * @graph: Media graph structure that was used to walk the graph | ||
287 | */ | ||
288 | void media_entity_graph_walk_cleanup(struct media_entity_graph *graph) | ||
289 | { | ||
290 | media_entity_enum_cleanup(&graph->ent_enum); | ||
291 | } | ||
292 | EXPORT_SYMBOL_GPL(media_entity_graph_walk_cleanup); | ||
293 | |||
138 | void media_entity_graph_walk_start(struct media_entity_graph *graph, | 294 | void media_entity_graph_walk_start(struct media_entity_graph *graph, |
139 | struct media_entity *entity) | 295 | struct media_entity *entity) |
140 | { | 296 | { |
297 | media_entity_enum_zero(&graph->ent_enum); | ||
298 | media_entity_enum_set(&graph->ent_enum, entity); | ||
299 | |||
141 | graph->top = 0; | 300 | graph->top = 0; |
142 | graph->stack[graph->top].entity = NULL; | 301 | graph->stack[graph->top].entity = NULL; |
143 | bitmap_zero(graph->entities, MEDIA_ENTITY_ENUM_MAX_ID); | ||
144 | |||
145 | if (WARN_ON(entity->id >= MEDIA_ENTITY_ENUM_MAX_ID)) | ||
146 | return; | ||
147 | |||
148 | __set_bit(entity->id, graph->entities); | ||
149 | stack_push(graph, entity); | 302 | stack_push(graph, entity); |
150 | } | 303 | } |
151 | EXPORT_SYMBOL_GPL(media_entity_graph_walk_start); | 304 | EXPORT_SYMBOL_GPL(media_entity_graph_walk_start); |
152 | 305 | ||
153 | /** | ||
154 | * media_entity_graph_walk_next - Get the next entity in the graph | ||
155 | * @graph: Media graph structure | ||
156 | * | ||
157 | * Perform a depth-first traversal of the given media entities graph. | ||
158 | * | ||
159 | * The graph structure must have been previously initialized with a call to | ||
160 | * media_entity_graph_walk_start(). | ||
161 | * | ||
162 | * Return the next entity in the graph or NULL if the whole graph have been | ||
163 | * traversed. | ||
164 | */ | ||
165 | struct media_entity * | 306 | struct media_entity * |
166 | media_entity_graph_walk_next(struct media_entity_graph *graph) | 307 | media_entity_graph_walk_next(struct media_entity_graph *graph) |
167 | { | 308 | { |
@@ -173,30 +314,30 @@ media_entity_graph_walk_next(struct media_entity_graph *graph) | |||
173 | * top of the stack until no more entities on the level can be | 314 | * top of the stack until no more entities on the level can be |
174 | * found. | 315 | * found. |
175 | */ | 316 | */ |
176 | while (link_top(graph) < stack_top(graph)->num_links) { | 317 | while (link_top(graph) != &stack_top(graph)->links) { |
177 | struct media_entity *entity = stack_top(graph); | 318 | struct media_entity *entity = stack_top(graph); |
178 | struct media_link *link = &entity->links[link_top(graph)]; | 319 | struct media_link *link; |
179 | struct media_entity *next; | 320 | struct media_entity *next; |
180 | 321 | ||
322 | link = list_entry(link_top(graph), typeof(*link), list); | ||
323 | |||
181 | /* The link is not enabled so we do not follow. */ | 324 | /* The link is not enabled so we do not follow. */ |
182 | if (!(link->flags & MEDIA_LNK_FL_ENABLED)) { | 325 | if (!(link->flags & MEDIA_LNK_FL_ENABLED)) { |
183 | link_top(graph)++; | 326 | link_top(graph) = link_top(graph)->next; |
184 | continue; | 327 | continue; |
185 | } | 328 | } |
186 | 329 | ||
187 | /* Get the entity in the other end of the link . */ | 330 | /* Get the entity in the other end of the link . */ |
188 | next = media_entity_other(entity, link); | 331 | next = media_entity_other(entity, link); |
189 | if (WARN_ON(next->id >= MEDIA_ENTITY_ENUM_MAX_ID)) | ||
190 | return NULL; | ||
191 | 332 | ||
192 | /* Has the entity already been visited? */ | 333 | /* Has the entity already been visited? */ |
193 | if (__test_and_set_bit(next->id, graph->entities)) { | 334 | if (media_entity_enum_test_and_set(&graph->ent_enum, next)) { |
194 | link_top(graph)++; | 335 | link_top(graph) = link_top(graph)->next; |
195 | continue; | 336 | continue; |
196 | } | 337 | } |
197 | 338 | ||
198 | /* Push the new entity to stack and start over. */ | 339 | /* Push the new entity to stack and start over. */ |
199 | link_top(graph)++; | 340 | link_top(graph) = link_top(graph)->next; |
200 | stack_push(graph, next); | 341 | stack_push(graph, next); |
201 | } | 342 | } |
202 | 343 | ||
@@ -208,39 +349,36 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next); | |||
208 | * Pipeline management | 349 | * Pipeline management |
209 | */ | 350 | */ |
210 | 351 | ||
211 | /** | ||
212 | * media_entity_pipeline_start - Mark a pipeline as streaming | ||
213 | * @entity: Starting entity | ||
214 | * @pipe: Media pipeline to be assigned to all entities in the pipeline. | ||
215 | * | ||
216 | * Mark all entities connected to a given entity through enabled links, either | ||
217 | * directly or indirectly, as streaming. The given pipeline object is assigned to | ||
218 | * every entity in the pipeline and stored in the media_entity pipe field. | ||
219 | * | ||
220 | * Calls to this function can be nested, in which case the same number of | ||
221 | * media_entity_pipeline_stop() calls will be required to stop streaming. The | ||
222 | * pipeline pointer must be identical for all nested calls to | ||
223 | * media_entity_pipeline_start(). | ||
224 | */ | ||
225 | __must_check int media_entity_pipeline_start(struct media_entity *entity, | 352 | __must_check int media_entity_pipeline_start(struct media_entity *entity, |
226 | struct media_pipeline *pipe) | 353 | struct media_pipeline *pipe) |
227 | { | 354 | { |
228 | struct media_device *mdev = entity->parent; | 355 | struct media_device *mdev = entity->graph_obj.mdev; |
229 | struct media_entity_graph graph; | 356 | struct media_entity_graph *graph = &pipe->graph; |
230 | struct media_entity *entity_err = entity; | 357 | struct media_entity *entity_err = entity; |
358 | struct media_link *link; | ||
231 | int ret; | 359 | int ret; |
232 | 360 | ||
233 | mutex_lock(&mdev->graph_mutex); | 361 | mutex_lock(&mdev->graph_mutex); |
234 | 362 | ||
235 | media_entity_graph_walk_start(&graph, entity); | 363 | if (!pipe->streaming_count++) { |
364 | ret = media_entity_graph_walk_init(&pipe->graph, mdev); | ||
365 | if (ret) | ||
366 | goto error_graph_walk_start; | ||
367 | } | ||
368 | |||
369 | media_entity_graph_walk_start(&pipe->graph, entity); | ||
236 | 370 | ||
237 | while ((entity = media_entity_graph_walk_next(&graph))) { | 371 | while ((entity = media_entity_graph_walk_next(graph))) { |
238 | DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS); | 372 | DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS); |
239 | DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS); | 373 | DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS); |
240 | unsigned int i; | ||
241 | 374 | ||
242 | entity->stream_count++; | 375 | entity->stream_count++; |
243 | WARN_ON(entity->pipe && entity->pipe != pipe); | 376 | |
377 | if (WARN_ON(entity->pipe && entity->pipe != pipe)) { | ||
378 | ret = -EBUSY; | ||
379 | goto error; | ||
380 | } | ||
381 | |||
244 | entity->pipe = pipe; | 382 | entity->pipe = pipe; |
245 | 383 | ||
246 | /* Already streaming --- no need to check. */ | 384 | /* Already streaming --- no need to check. */ |
@@ -253,8 +391,7 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, | |||
253 | bitmap_zero(active, entity->num_pads); | 391 | bitmap_zero(active, entity->num_pads); |
254 | bitmap_fill(has_no_links, entity->num_pads); | 392 | bitmap_fill(has_no_links, entity->num_pads); |
255 | 393 | ||
256 | for (i = 0; i < entity->num_links; i++) { | 394 | list_for_each_entry(link, &entity->links, list) { |
257 | struct media_link *link = &entity->links[i]; | ||
258 | struct media_pad *pad = link->sink->entity == entity | 395 | struct media_pad *pad = link->sink->entity == entity |
259 | ? link->sink : link->source; | 396 | ? link->sink : link->source; |
260 | 397 | ||
@@ -280,7 +417,7 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, | |||
280 | 417 | ||
281 | ret = entity->ops->link_validate(link); | 418 | ret = entity->ops->link_validate(link); |
282 | if (ret < 0 && ret != -ENOIOCTLCMD) { | 419 | if (ret < 0 && ret != -ENOIOCTLCMD) { |
283 | dev_dbg(entity->parent->dev, | 420 | dev_dbg(entity->graph_obj.mdev->dev, |
284 | "link validation failed for \"%s\":%u -> \"%s\":%u, error %d\n", | 421 | "link validation failed for \"%s\":%u -> \"%s\":%u, error %d\n", |
285 | link->source->entity->name, | 422 | link->source->entity->name, |
286 | link->source->index, | 423 | link->source->index, |
@@ -294,7 +431,7 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity, | |||
294 | 431 | ||
295 | if (!bitmap_full(active, entity->num_pads)) { | 432 | if (!bitmap_full(active, entity->num_pads)) { |
296 | ret = -EPIPE; | 433 | ret = -EPIPE; |
297 | dev_dbg(entity->parent->dev, | 434 | dev_dbg(entity->graph_obj.mdev->dev, |
298 | "\"%s\":%u must be connected by an enabled link\n", | 435 | "\"%s\":%u must be connected by an enabled link\n", |
299 | entity->name, | 436 | entity->name, |
300 | (unsigned)find_first_zero_bit( | 437 | (unsigned)find_first_zero_bit( |
@@ -312,9 +449,9 @@ error: | |||
312 | * Link validation on graph failed. We revert what we did and | 449 | * Link validation on graph failed. We revert what we did and |
313 | * return the error. | 450 | * return the error. |
314 | */ | 451 | */ |
315 | media_entity_graph_walk_start(&graph, entity_err); | 452 | media_entity_graph_walk_start(graph, entity_err); |
316 | 453 | ||
317 | while ((entity_err = media_entity_graph_walk_next(&graph))) { | 454 | while ((entity_err = media_entity_graph_walk_next(graph))) { |
318 | entity_err->stream_count--; | 455 | entity_err->stream_count--; |
319 | if (entity_err->stream_count == 0) | 456 | if (entity_err->stream_count == 0) |
320 | entity_err->pipe = NULL; | 457 | entity_err->pipe = NULL; |
@@ -327,39 +464,36 @@ error: | |||
327 | break; | 464 | break; |
328 | } | 465 | } |
329 | 466 | ||
467 | error_graph_walk_start: | ||
468 | if (!--pipe->streaming_count) | ||
469 | media_entity_graph_walk_cleanup(graph); | ||
470 | |||
330 | mutex_unlock(&mdev->graph_mutex); | 471 | mutex_unlock(&mdev->graph_mutex); |
331 | 472 | ||
332 | return ret; | 473 | return ret; |
333 | } | 474 | } |
334 | EXPORT_SYMBOL_GPL(media_entity_pipeline_start); | 475 | EXPORT_SYMBOL_GPL(media_entity_pipeline_start); |
335 | 476 | ||
336 | /** | ||
337 | * media_entity_pipeline_stop - Mark a pipeline as not streaming | ||
338 | * @entity: Starting entity | ||
339 | * | ||
340 | * Mark all entities connected to a given entity through enabled links, either | ||
341 | * directly or indirectly, as not streaming. The media_entity pipe field is | ||
342 | * reset to NULL. | ||
343 | * | ||
344 | * If multiple calls to media_entity_pipeline_start() have been made, the same | ||
345 | * number of calls to this function are required to mark the pipeline as not | ||
346 | * streaming. | ||
347 | */ | ||
348 | void media_entity_pipeline_stop(struct media_entity *entity) | 477 | void media_entity_pipeline_stop(struct media_entity *entity) |
349 | { | 478 | { |
350 | struct media_device *mdev = entity->parent; | 479 | struct media_device *mdev = entity->graph_obj.mdev; |
351 | struct media_entity_graph graph; | 480 | struct media_entity_graph *graph = &entity->pipe->graph; |
481 | struct media_pipeline *pipe = entity->pipe; | ||
352 | 482 | ||
353 | mutex_lock(&mdev->graph_mutex); | 483 | mutex_lock(&mdev->graph_mutex); |
354 | 484 | ||
355 | media_entity_graph_walk_start(&graph, entity); | 485 | WARN_ON(!pipe->streaming_count); |
486 | media_entity_graph_walk_start(graph, entity); | ||
356 | 487 | ||
357 | while ((entity = media_entity_graph_walk_next(&graph))) { | 488 | while ((entity = media_entity_graph_walk_next(graph))) { |
358 | entity->stream_count--; | 489 | entity->stream_count--; |
359 | if (entity->stream_count == 0) | 490 | if (entity->stream_count == 0) |
360 | entity->pipe = NULL; | 491 | entity->pipe = NULL; |
361 | } | 492 | } |
362 | 493 | ||
494 | if (!--pipe->streaming_count) | ||
495 | media_entity_graph_walk_cleanup(graph); | ||
496 | |||
363 | mutex_unlock(&mdev->graph_mutex); | 497 | mutex_unlock(&mdev->graph_mutex); |
364 | } | 498 | } |
365 | EXPORT_SYMBOL_GPL(media_entity_pipeline_stop); | 499 | EXPORT_SYMBOL_GPL(media_entity_pipeline_stop); |
@@ -368,44 +502,26 @@ EXPORT_SYMBOL_GPL(media_entity_pipeline_stop); | |||
368 | * Module use count | 502 | * Module use count |
369 | */ | 503 | */ |
370 | 504 | ||
371 | /* | ||
372 | * media_entity_get - Get a reference to the parent module | ||
373 | * @entity: The entity | ||
374 | * | ||
375 | * Get a reference to the parent media device module. | ||
376 | * | ||
377 | * The function will return immediately if @entity is NULL. | ||
378 | * | ||
379 | * Return a pointer to the entity on success or NULL on failure. | ||
380 | */ | ||
381 | struct media_entity *media_entity_get(struct media_entity *entity) | 505 | struct media_entity *media_entity_get(struct media_entity *entity) |
382 | { | 506 | { |
383 | if (entity == NULL) | 507 | if (entity == NULL) |
384 | return NULL; | 508 | return NULL; |
385 | 509 | ||
386 | if (entity->parent->dev && | 510 | if (entity->graph_obj.mdev->dev && |
387 | !try_module_get(entity->parent->dev->driver->owner)) | 511 | !try_module_get(entity->graph_obj.mdev->dev->driver->owner)) |
388 | return NULL; | 512 | return NULL; |
389 | 513 | ||
390 | return entity; | 514 | return entity; |
391 | } | 515 | } |
392 | EXPORT_SYMBOL_GPL(media_entity_get); | 516 | EXPORT_SYMBOL_GPL(media_entity_get); |
393 | 517 | ||
394 | /* | ||
395 | * media_entity_put - Release the reference to the parent module | ||
396 | * @entity: The entity | ||
397 | * | ||
398 | * Release the reference count acquired by media_entity_get(). | ||
399 | * | ||
400 | * The function will return immediately if @entity is NULL. | ||
401 | */ | ||
402 | void media_entity_put(struct media_entity *entity) | 518 | void media_entity_put(struct media_entity *entity) |
403 | { | 519 | { |
404 | if (entity == NULL) | 520 | if (entity == NULL) |
405 | return; | 521 | return; |
406 | 522 | ||
407 | if (entity->parent->dev) | 523 | if (entity->graph_obj.mdev->dev) |
408 | module_put(entity->parent->dev->driver->owner); | 524 | module_put(entity->graph_obj.mdev->dev->driver->owner); |
409 | } | 525 | } |
410 | EXPORT_SYMBOL_GPL(media_entity_put); | 526 | EXPORT_SYMBOL_GPL(media_entity_put); |
411 | 527 | ||
@@ -413,29 +529,52 @@ EXPORT_SYMBOL_GPL(media_entity_put); | |||
413 | * Links management | 529 | * Links management |
414 | */ | 530 | */ |
415 | 531 | ||
416 | static struct media_link *media_entity_add_link(struct media_entity *entity) | 532 | static struct media_link *media_add_link(struct list_head *head) |
417 | { | 533 | { |
418 | if (entity->num_links >= entity->max_links) { | 534 | struct media_link *link; |
419 | struct media_link *links = entity->links; | 535 | |
420 | unsigned int max_links = entity->max_links + 2; | 536 | link = kzalloc(sizeof(*link), GFP_KERNEL); |
421 | unsigned int i; | 537 | if (link == NULL) |
538 | return NULL; | ||
422 | 539 | ||
423 | links = krealloc(links, max_links * sizeof(*links), GFP_KERNEL); | 540 | list_add_tail(&link->list, head); |
424 | if (links == NULL) | ||
425 | return NULL; | ||
426 | 541 | ||
427 | for (i = 0; i < entity->num_links; i++) | 542 | return link; |
428 | links[i].reverse->reverse = &links[i]; | 543 | } |
429 | 544 | ||
430 | entity->max_links = max_links; | 545 | static void __media_entity_remove_link(struct media_entity *entity, |
431 | entity->links = links; | 546 | struct media_link *link) |
432 | } | 547 | { |
548 | struct media_link *rlink, *tmp; | ||
549 | struct media_entity *remote; | ||
550 | |||
551 | if (link->source->entity == entity) | ||
552 | remote = link->sink->entity; | ||
553 | else | ||
554 | remote = link->source->entity; | ||
433 | 555 | ||
434 | return &entity->links[entity->num_links++]; | 556 | list_for_each_entry_safe(rlink, tmp, &remote->links, list) { |
557 | if (rlink != link->reverse) | ||
558 | continue; | ||
559 | |||
560 | if (link->source->entity == entity) | ||
561 | remote->num_backlinks--; | ||
562 | |||
563 | /* Remove the remote link */ | ||
564 | list_del(&rlink->list); | ||
565 | media_gobj_destroy(&rlink->graph_obj); | ||
566 | kfree(rlink); | ||
567 | |||
568 | if (--remote->num_links == 0) | ||
569 | break; | ||
570 | } | ||
571 | list_del(&link->list); | ||
572 | media_gobj_destroy(&link->graph_obj); | ||
573 | kfree(link); | ||
435 | } | 574 | } |
436 | 575 | ||
437 | int | 576 | int |
438 | media_entity_create_link(struct media_entity *source, u16 source_pad, | 577 | media_create_pad_link(struct media_entity *source, u16 source_pad, |
439 | struct media_entity *sink, u16 sink_pad, u32 flags) | 578 | struct media_entity *sink, u16 sink_pad, u32 flags) |
440 | { | 579 | { |
441 | struct media_link *link; | 580 | struct media_link *link; |
@@ -445,68 +584,118 @@ media_entity_create_link(struct media_entity *source, u16 source_pad, | |||
445 | BUG_ON(source_pad >= source->num_pads); | 584 | BUG_ON(source_pad >= source->num_pads); |
446 | BUG_ON(sink_pad >= sink->num_pads); | 585 | BUG_ON(sink_pad >= sink->num_pads); |
447 | 586 | ||
448 | link = media_entity_add_link(source); | 587 | link = media_add_link(&source->links); |
449 | if (link == NULL) | 588 | if (link == NULL) |
450 | return -ENOMEM; | 589 | return -ENOMEM; |
451 | 590 | ||
452 | link->source = &source->pads[source_pad]; | 591 | link->source = &source->pads[source_pad]; |
453 | link->sink = &sink->pads[sink_pad]; | 592 | link->sink = &sink->pads[sink_pad]; |
454 | link->flags = flags; | 593 | link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK; |
594 | |||
595 | /* Initialize graph object embedded at the new link */ | ||
596 | media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK, | ||
597 | &link->graph_obj); | ||
455 | 598 | ||
456 | /* Create the backlink. Backlinks are used to help graph traversal and | 599 | /* Create the backlink. Backlinks are used to help graph traversal and |
457 | * are not reported to userspace. | 600 | * are not reported to userspace. |
458 | */ | 601 | */ |
459 | backlink = media_entity_add_link(sink); | 602 | backlink = media_add_link(&sink->links); |
460 | if (backlink == NULL) { | 603 | if (backlink == NULL) { |
461 | source->num_links--; | 604 | __media_entity_remove_link(source, link); |
462 | return -ENOMEM; | 605 | return -ENOMEM; |
463 | } | 606 | } |
464 | 607 | ||
465 | backlink->source = &source->pads[source_pad]; | 608 | backlink->source = &source->pads[source_pad]; |
466 | backlink->sink = &sink->pads[sink_pad]; | 609 | backlink->sink = &sink->pads[sink_pad]; |
467 | backlink->flags = flags; | 610 | backlink->flags = flags; |
611 | backlink->is_backlink = true; | ||
612 | |||
613 | /* Initialize graph object embedded at the new link */ | ||
614 | media_gobj_create(sink->graph_obj.mdev, MEDIA_GRAPH_LINK, | ||
615 | &backlink->graph_obj); | ||
468 | 616 | ||
469 | link->reverse = backlink; | 617 | link->reverse = backlink; |
470 | backlink->reverse = link; | 618 | backlink->reverse = link; |
471 | 619 | ||
472 | sink->num_backlinks++; | 620 | sink->num_backlinks++; |
621 | sink->num_links++; | ||
622 | source->num_links++; | ||
473 | 623 | ||
474 | return 0; | 624 | return 0; |
475 | } | 625 | } |
476 | EXPORT_SYMBOL_GPL(media_entity_create_link); | 626 | EXPORT_SYMBOL_GPL(media_create_pad_link); |
477 | 627 | ||
478 | void __media_entity_remove_links(struct media_entity *entity) | 628 | int media_create_pad_links(const struct media_device *mdev, |
629 | const u32 source_function, | ||
630 | struct media_entity *source, | ||
631 | const u16 source_pad, | ||
632 | const u32 sink_function, | ||
633 | struct media_entity *sink, | ||
634 | const u16 sink_pad, | ||
635 | u32 flags, | ||
636 | const bool allow_both_undefined) | ||
479 | { | 637 | { |
480 | unsigned int i; | 638 | struct media_entity *entity; |
481 | 639 | unsigned function; | |
482 | for (i = 0; i < entity->num_links; i++) { | 640 | int ret; |
483 | struct media_link *link = &entity->links[i]; | ||
484 | struct media_entity *remote; | ||
485 | unsigned int r = 0; | ||
486 | |||
487 | if (link->source->entity == entity) | ||
488 | remote = link->sink->entity; | ||
489 | else | ||
490 | remote = link->source->entity; | ||
491 | |||
492 | while (r < remote->num_links) { | ||
493 | struct media_link *rlink = &remote->links[r]; | ||
494 | 641 | ||
495 | if (rlink != link->reverse) { | 642 | /* Trivial case: 1:1 relation */ |
496 | r++; | 643 | if (source && sink) |
644 | return media_create_pad_link(source, source_pad, | ||
645 | sink, sink_pad, flags); | ||
646 | |||
647 | /* Worse case scenario: n:n relation */ | ||
648 | if (!source && !sink) { | ||
649 | if (!allow_both_undefined) | ||
650 | return 0; | ||
651 | media_device_for_each_entity(source, mdev) { | ||
652 | if (source->function != source_function) | ||
497 | continue; | 653 | continue; |
654 | media_device_for_each_entity(sink, mdev) { | ||
655 | if (sink->function != sink_function) | ||
656 | continue; | ||
657 | ret = media_create_pad_link(source, source_pad, | ||
658 | sink, sink_pad, | ||
659 | flags); | ||
660 | if (ret) | ||
661 | return ret; | ||
662 | flags &= ~(MEDIA_LNK_FL_ENABLED | | ||
663 | MEDIA_LNK_FL_IMMUTABLE); | ||
498 | } | 664 | } |
665 | } | ||
666 | return 0; | ||
667 | } | ||
499 | 668 | ||
500 | if (link->source->entity == entity) | 669 | /* Handle 1:n and n:1 cases */ |
501 | remote->num_backlinks--; | 670 | if (source) |
671 | function = sink_function; | ||
672 | else | ||
673 | function = source_function; | ||
502 | 674 | ||
503 | if (--remote->num_links == 0) | 675 | media_device_for_each_entity(entity, mdev) { |
504 | break; | 676 | if (entity->function != function) |
677 | continue; | ||
505 | 678 | ||
506 | /* Insert last entry in place of the dropped link. */ | 679 | if (source) |
507 | *rlink = remote->links[remote->num_links]; | 680 | ret = media_create_pad_link(source, source_pad, |
508 | } | 681 | entity, sink_pad, flags); |
682 | else | ||
683 | ret = media_create_pad_link(entity, source_pad, | ||
684 | sink, sink_pad, flags); | ||
685 | if (ret) | ||
686 | return ret; | ||
687 | flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); | ||
509 | } | 688 | } |
689 | return 0; | ||
690 | } | ||
691 | EXPORT_SYMBOL_GPL(media_create_pad_links); | ||
692 | |||
693 | void __media_entity_remove_links(struct media_entity *entity) | ||
694 | { | ||
695 | struct media_link *link, *tmp; | ||
696 | |||
697 | list_for_each_entry_safe(link, tmp, &entity->links, list) | ||
698 | __media_entity_remove_link(entity, link); | ||
510 | 699 | ||
511 | entity->num_links = 0; | 700 | entity->num_links = 0; |
512 | entity->num_backlinks = 0; | 701 | entity->num_backlinks = 0; |
@@ -515,13 +704,15 @@ EXPORT_SYMBOL_GPL(__media_entity_remove_links); | |||
515 | 704 | ||
516 | void media_entity_remove_links(struct media_entity *entity) | 705 | void media_entity_remove_links(struct media_entity *entity) |
517 | { | 706 | { |
707 | struct media_device *mdev = entity->graph_obj.mdev; | ||
708 | |||
518 | /* Do nothing if the entity is not registered. */ | 709 | /* Do nothing if the entity is not registered. */ |
519 | if (entity->parent == NULL) | 710 | if (mdev == NULL) |
520 | return; | 711 | return; |
521 | 712 | ||
522 | mutex_lock(&entity->parent->graph_mutex); | 713 | spin_lock(&mdev->lock); |
523 | __media_entity_remove_links(entity); | 714 | __media_entity_remove_links(entity); |
524 | mutex_unlock(&entity->parent->graph_mutex); | 715 | spin_unlock(&mdev->lock); |
525 | } | 716 | } |
526 | EXPORT_SYMBOL_GPL(media_entity_remove_links); | 717 | EXPORT_SYMBOL_GPL(media_entity_remove_links); |
527 | 718 | ||
@@ -549,20 +740,6 @@ static int __media_entity_setup_link_notify(struct media_link *link, u32 flags) | |||
549 | return 0; | 740 | return 0; |
550 | } | 741 | } |
551 | 742 | ||
552 | /** | ||
553 | * __media_entity_setup_link - Configure a media link | ||
554 | * @link: The link being configured | ||
555 | * @flags: Link configuration flags | ||
556 | * | ||
557 | * The bulk of link setup is handled by the two entities connected through the | ||
558 | * link. This function notifies both entities of the link configuration change. | ||
559 | * | ||
560 | * If the link is immutable or if the current and new configuration are | ||
561 | * identical, return immediately. | ||
562 | * | ||
563 | * The user is expected to hold link->source->parent->mutex. If not, | ||
564 | * media_entity_setup_link() should be used instead. | ||
565 | */ | ||
566 | int __media_entity_setup_link(struct media_link *link, u32 flags) | 743 | int __media_entity_setup_link(struct media_link *link, u32 flags) |
567 | { | 744 | { |
568 | const u32 mask = MEDIA_LNK_FL_ENABLED; | 745 | const u32 mask = MEDIA_LNK_FL_ENABLED; |
@@ -590,7 +767,7 @@ int __media_entity_setup_link(struct media_link *link, u32 flags) | |||
590 | (source->stream_count || sink->stream_count)) | 767 | (source->stream_count || sink->stream_count)) |
591 | return -EBUSY; | 768 | return -EBUSY; |
592 | 769 | ||
593 | mdev = source->parent; | 770 | mdev = source->graph_obj.mdev; |
594 | 771 | ||
595 | if (mdev->link_notify) { | 772 | if (mdev->link_notify) { |
596 | ret = mdev->link_notify(link, flags, | 773 | ret = mdev->link_notify(link, flags, |
@@ -611,31 +788,20 @@ int media_entity_setup_link(struct media_link *link, u32 flags) | |||
611 | { | 788 | { |
612 | int ret; | 789 | int ret; |
613 | 790 | ||
614 | mutex_lock(&link->source->entity->parent->graph_mutex); | 791 | mutex_lock(&link->graph_obj.mdev->graph_mutex); |
615 | ret = __media_entity_setup_link(link, flags); | 792 | ret = __media_entity_setup_link(link, flags); |
616 | mutex_unlock(&link->source->entity->parent->graph_mutex); | 793 | mutex_unlock(&link->graph_obj.mdev->graph_mutex); |
617 | 794 | ||
618 | return ret; | 795 | return ret; |
619 | } | 796 | } |
620 | EXPORT_SYMBOL_GPL(media_entity_setup_link); | 797 | EXPORT_SYMBOL_GPL(media_entity_setup_link); |
621 | 798 | ||
622 | /** | ||
623 | * media_entity_find_link - Find a link between two pads | ||
624 | * @source: Source pad | ||
625 | * @sink: Sink pad | ||
626 | * | ||
627 | * Return a pointer to the link between the two entities. If no such link | ||
628 | * exists, return NULL. | ||
629 | */ | ||
630 | struct media_link * | 799 | struct media_link * |
631 | media_entity_find_link(struct media_pad *source, struct media_pad *sink) | 800 | media_entity_find_link(struct media_pad *source, struct media_pad *sink) |
632 | { | 801 | { |
633 | struct media_link *link; | 802 | struct media_link *link; |
634 | unsigned int i; | ||
635 | |||
636 | for (i = 0; i < source->entity->num_links; ++i) { | ||
637 | link = &source->entity->links[i]; | ||
638 | 803 | ||
804 | list_for_each_entry(link, &source->entity->links, list) { | ||
639 | if (link->source->entity == source->entity && | 805 | if (link->source->entity == source->entity && |
640 | link->source->index == source->index && | 806 | link->source->index == source->index && |
641 | link->sink->entity == sink->entity && | 807 | link->sink->entity == sink->entity && |
@@ -647,23 +813,11 @@ media_entity_find_link(struct media_pad *source, struct media_pad *sink) | |||
647 | } | 813 | } |
648 | EXPORT_SYMBOL_GPL(media_entity_find_link); | 814 | EXPORT_SYMBOL_GPL(media_entity_find_link); |
649 | 815 | ||
650 | /** | ||
651 | * media_entity_remote_pad - Find the pad at the remote end of a link | ||
652 | * @pad: Pad at the local end of the link | ||
653 | * | ||
654 | * Search for a remote pad connected to the given pad by iterating over all | ||
655 | * links originating or terminating at that pad until an enabled link is found. | ||
656 | * | ||
657 | * Return a pointer to the pad at the remote end of the first found enabled | ||
658 | * link, or NULL if no enabled link has been found. | ||
659 | */ | ||
660 | struct media_pad *media_entity_remote_pad(struct media_pad *pad) | 816 | struct media_pad *media_entity_remote_pad(struct media_pad *pad) |
661 | { | 817 | { |
662 | unsigned int i; | 818 | struct media_link *link; |
663 | |||
664 | for (i = 0; i < pad->entity->num_links; i++) { | ||
665 | struct media_link *link = &pad->entity->links[i]; | ||
666 | 819 | ||
820 | list_for_each_entry(link, &pad->entity->links, list) { | ||
667 | if (!(link->flags & MEDIA_LNK_FL_ENABLED)) | 821 | if (!(link->flags & MEDIA_LNK_FL_ENABLED)) |
668 | continue; | 822 | continue; |
669 | 823 | ||
@@ -678,3 +832,113 @@ struct media_pad *media_entity_remote_pad(struct media_pad *pad) | |||
678 | 832 | ||
679 | } | 833 | } |
680 | EXPORT_SYMBOL_GPL(media_entity_remote_pad); | 834 | EXPORT_SYMBOL_GPL(media_entity_remote_pad); |
835 | |||
836 | static void media_interface_init(struct media_device *mdev, | ||
837 | struct media_interface *intf, | ||
838 | u32 gobj_type, | ||
839 | u32 intf_type, u32 flags) | ||
840 | { | ||
841 | intf->type = intf_type; | ||
842 | intf->flags = flags; | ||
843 | INIT_LIST_HEAD(&intf->links); | ||
844 | |||
845 | media_gobj_create(mdev, gobj_type, &intf->graph_obj); | ||
846 | } | ||
847 | |||
848 | /* Functions related to the media interface via device nodes */ | ||
849 | |||
850 | struct media_intf_devnode *media_devnode_create(struct media_device *mdev, | ||
851 | u32 type, u32 flags, | ||
852 | u32 major, u32 minor) | ||
853 | { | ||
854 | struct media_intf_devnode *devnode; | ||
855 | |||
856 | devnode = kzalloc(sizeof(*devnode), GFP_KERNEL); | ||
857 | if (!devnode) | ||
858 | return NULL; | ||
859 | |||
860 | devnode->major = major; | ||
861 | devnode->minor = minor; | ||
862 | |||
863 | media_interface_init(mdev, &devnode->intf, MEDIA_GRAPH_INTF_DEVNODE, | ||
864 | type, flags); | ||
865 | |||
866 | return devnode; | ||
867 | } | ||
868 | EXPORT_SYMBOL_GPL(media_devnode_create); | ||
869 | |||
870 | void media_devnode_remove(struct media_intf_devnode *devnode) | ||
871 | { | ||
872 | media_remove_intf_links(&devnode->intf); | ||
873 | media_gobj_destroy(&devnode->intf.graph_obj); | ||
874 | kfree(devnode); | ||
875 | } | ||
876 | EXPORT_SYMBOL_GPL(media_devnode_remove); | ||
877 | |||
878 | struct media_link *media_create_intf_link(struct media_entity *entity, | ||
879 | struct media_interface *intf, | ||
880 | u32 flags) | ||
881 | { | ||
882 | struct media_link *link; | ||
883 | |||
884 | link = media_add_link(&intf->links); | ||
885 | if (link == NULL) | ||
886 | return NULL; | ||
887 | |||
888 | link->intf = intf; | ||
889 | link->entity = entity; | ||
890 | link->flags = flags | MEDIA_LNK_FL_INTERFACE_LINK; | ||
891 | |||
892 | /* Initialize graph object embedded at the new link */ | ||
893 | media_gobj_create(intf->graph_obj.mdev, MEDIA_GRAPH_LINK, | ||
894 | &link->graph_obj); | ||
895 | |||
896 | return link; | ||
897 | } | ||
898 | EXPORT_SYMBOL_GPL(media_create_intf_link); | ||
899 | |||
900 | void __media_remove_intf_link(struct media_link *link) | ||
901 | { | ||
902 | list_del(&link->list); | ||
903 | media_gobj_destroy(&link->graph_obj); | ||
904 | kfree(link); | ||
905 | } | ||
906 | EXPORT_SYMBOL_GPL(__media_remove_intf_link); | ||
907 | |||
908 | void media_remove_intf_link(struct media_link *link) | ||
909 | { | ||
910 | struct media_device *mdev = link->graph_obj.mdev; | ||
911 | |||
912 | /* Do nothing if the intf is not registered. */ | ||
913 | if (mdev == NULL) | ||
914 | return; | ||
915 | |||
916 | spin_lock(&mdev->lock); | ||
917 | __media_remove_intf_link(link); | ||
918 | spin_unlock(&mdev->lock); | ||
919 | } | ||
920 | EXPORT_SYMBOL_GPL(media_remove_intf_link); | ||
921 | |||
922 | void __media_remove_intf_links(struct media_interface *intf) | ||
923 | { | ||
924 | struct media_link *link, *tmp; | ||
925 | |||
926 | list_for_each_entry_safe(link, tmp, &intf->links, list) | ||
927 | __media_remove_intf_link(link); | ||
928 | |||
929 | } | ||
930 | EXPORT_SYMBOL_GPL(__media_remove_intf_links); | ||
931 | |||
932 | void media_remove_intf_links(struct media_interface *intf) | ||
933 | { | ||
934 | struct media_device *mdev = intf->graph_obj.mdev; | ||
935 | |||
936 | /* Do nothing if the intf is not registered. */ | ||
937 | if (mdev == NULL) | ||
938 | return; | ||
939 | |||
940 | spin_lock(&mdev->lock); | ||
941 | __media_remove_intf_links(intf); | ||
942 | spin_unlock(&mdev->lock); | ||
943 | } | ||
944 | EXPORT_SYMBOL_GPL(media_remove_intf_links); | ||
diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c index c5cc14ef8347..da8b414fd824 100644 --- a/drivers/media/pci/bt8xx/dst_ca.c +++ b/drivers/media/pci/bt8xx/dst_ca.c | |||
@@ -705,7 +705,8 @@ struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_ | |||
705 | struct dvb_device *dvbdev; | 705 | struct dvb_device *dvbdev; |
706 | 706 | ||
707 | dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device"); | 707 | dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device"); |
708 | if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) { | 708 | if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, |
709 | DVB_DEVICE_CA, 0) == 0) { | ||
709 | dst->dst_ca = dvbdev; | 710 | dst->dst_ca = dvbdev; |
710 | return dst->dst_ca; | 711 | return dst->dst_ca; |
711 | } | 712 | } |
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index fba5b40a869c..9d5b314142f1 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c | |||
@@ -1065,7 +1065,7 @@ static int ddb_ci_attach(struct ddb_port *port) | |||
1065 | port->en, 0, 1); | 1065 | port->en, 0, 1); |
1066 | ret = dvb_register_device(&port->output->adap, &port->output->dev, | 1066 | ret = dvb_register_device(&port->output->adap, &port->output->dev, |
1067 | &dvbdev_ci, (void *) port->output, | 1067 | &dvbdev_ci, (void *) port->output, |
1068 | DVB_DEVICE_SEC); | 1068 | DVB_DEVICE_SEC, 0); |
1069 | return ret; | 1069 | return ret; |
1070 | } | 1070 | } |
1071 | 1071 | ||
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c index 1b92d836a564..4e924e2d1638 100644 --- a/drivers/media/pci/ngene/ngene-core.c +++ b/drivers/media/pci/ngene/ngene-core.c | |||
@@ -1513,7 +1513,7 @@ static int init_channel(struct ngene_channel *chan) | |||
1513 | set_transfer(&chan->dev->channel[2], 1); | 1513 | set_transfer(&chan->dev->channel[2], 1); |
1514 | dvb_register_device(adapter, &chan->ci_dev, | 1514 | dvb_register_device(adapter, &chan->ci_dev, |
1515 | &ngene_dvbdev_ci, (void *) chan, | 1515 | &ngene_dvbdev_ci, (void *) chan, |
1516 | DVB_DEVICE_SEC); | 1516 | DVB_DEVICE_SEC, 0); |
1517 | if (!chan->ci_dev) | 1517 | if (!chan->ci_dev) |
1518 | goto err; | 1518 | goto err; |
1519 | } | 1519 | } |
diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index 5e18b6796ed9..a69dc6a0752b 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c | |||
@@ -1358,7 +1358,7 @@ static int av7110_register(struct av7110 *av7110) | |||
1358 | 1358 | ||
1359 | #ifdef CONFIG_DVB_AV7110_OSD | 1359 | #ifdef CONFIG_DVB_AV7110_OSD |
1360 | dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev, | 1360 | dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev, |
1361 | &dvbdev_osd, av7110, DVB_DEVICE_OSD); | 1361 | &dvbdev_osd, av7110, DVB_DEVICE_OSD, 0); |
1362 | #endif | 1362 | #endif |
1363 | 1363 | ||
1364 | dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx); | 1364 | dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx); |
diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c index 6fc748e22017..26c5696c193b 100644 --- a/drivers/media/pci/ttpci/av7110_av.c +++ b/drivers/media/pci/ttpci/av7110_av.c | |||
@@ -1594,10 +1594,10 @@ int av7110_av_register(struct av7110 *av7110) | |||
1594 | memset(&av7110->video_size, 0, sizeof (video_size_t)); | 1594 | memset(&av7110->video_size, 0, sizeof (video_size_t)); |
1595 | 1595 | ||
1596 | dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev, | 1596 | dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev, |
1597 | &dvbdev_video, av7110, DVB_DEVICE_VIDEO); | 1597 | &dvbdev_video, av7110, DVB_DEVICE_VIDEO, 0); |
1598 | 1598 | ||
1599 | dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev, | 1599 | dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev, |
1600 | &dvbdev_audio, av7110, DVB_DEVICE_AUDIO); | 1600 | &dvbdev_audio, av7110, DVB_DEVICE_AUDIO, 0); |
1601 | 1601 | ||
1602 | return 0; | 1602 | return 0; |
1603 | } | 1603 | } |
diff --git a/drivers/media/pci/ttpci/av7110_ca.c b/drivers/media/pci/ttpci/av7110_ca.c index bc4c65ffd4b9..96a130fb4595 100644 --- a/drivers/media/pci/ttpci/av7110_ca.c +++ b/drivers/media/pci/ttpci/av7110_ca.c | |||
@@ -378,7 +378,7 @@ static struct dvb_device dvbdev_ca = { | |||
378 | int av7110_ca_register(struct av7110 *av7110) | 378 | int av7110_ca_register(struct av7110 *av7110) |
379 | { | 379 | { |
380 | return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev, | 380 | return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev, |
381 | &dvbdev_ca, av7110, DVB_DEVICE_CA); | 381 | &dvbdev_ca, av7110, DVB_DEVICE_CA, 0); |
382 | } | 382 | } |
383 | 383 | ||
384 | void av7110_ca_unregister(struct av7110 *av7110) | 384 | void av7110_ca_unregister(struct av7110 *av7110) |
diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c index b6716c57b5db..b90f5bb15517 100644 --- a/drivers/media/platform/exynos4-is/common.c +++ b/drivers/media/platform/exynos4-is/common.c | |||
@@ -22,8 +22,7 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity) | |||
22 | while (pad->flags & MEDIA_PAD_FL_SINK) { | 22 | while (pad->flags & MEDIA_PAD_FL_SINK) { |
23 | /* source pad */ | 23 | /* source pad */ |
24 | pad = media_entity_remote_pad(pad); | 24 | pad = media_entity_remote_pad(pad); |
25 | if (pad == NULL || | 25 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
26 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
27 | break; | 26 | break; |
28 | 27 | ||
29 | sd = media_entity_to_v4l2_subdev(pad->entity); | 28 | sd = media_entity_to_v4l2_subdev(pad->entity); |
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 0d549a6c8a13..bf47d3b9cbe7 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c | |||
@@ -1136,8 +1136,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc) | |||
1136 | } | 1136 | } |
1137 | } | 1137 | } |
1138 | 1138 | ||
1139 | if (src_pad == NULL || | 1139 | if (!src_pad || !is_media_entity_v4l2_subdev(src_pad->entity)) |
1140 | media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
1141 | break; | 1140 | break; |
1142 | 1141 | ||
1143 | /* Don't call FIMC subdev operation to avoid nested locking */ | 1142 | /* Don't call FIMC subdev operation to avoid nested locking */ |
@@ -1392,7 +1391,7 @@ static int fimc_link_setup(struct media_entity *entity, | |||
1392 | struct fimc_vid_cap *vc = &fimc->vid_cap; | 1391 | struct fimc_vid_cap *vc = &fimc->vid_cap; |
1393 | struct v4l2_subdev *sensor; | 1392 | struct v4l2_subdev *sensor; |
1394 | 1393 | ||
1395 | if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | 1394 | if (!is_media_entity_v4l2_subdev(remote->entity)) |
1396 | return -EINVAL; | 1395 | return -EINVAL; |
1397 | 1396 | ||
1398 | if (WARN_ON(fimc == NULL)) | 1397 | if (WARN_ON(fimc == NULL)) |
@@ -1800,7 +1799,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, | |||
1800 | vid_cap->wb_fmt.code = fmt->mbus_code; | 1799 | vid_cap->wb_fmt.code = fmt->mbus_code; |
1801 | 1800 | ||
1802 | vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; | 1801 | vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; |
1803 | ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); | 1802 | ret = media_entity_pads_init(&vfd->entity, 1, &vid_cap->vd_pad); |
1804 | if (ret) | 1803 | if (ret) |
1805 | goto err_free_ctx; | 1804 | goto err_free_ctx; |
1806 | 1805 | ||
@@ -1892,8 +1891,8 @@ int fimc_initialize_capture_subdev(struct fimc_dev *fimc) | |||
1892 | fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK_CAM].flags = MEDIA_PAD_FL_SINK; | 1891 | fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK_CAM].flags = MEDIA_PAD_FL_SINK; |
1893 | fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK_FIFO].flags = MEDIA_PAD_FL_SINK; | 1892 | fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK_FIFO].flags = MEDIA_PAD_FL_SINK; |
1894 | fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; | 1893 | fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; |
1895 | ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM, | 1894 | ret = media_entity_pads_init(&sd->entity, FIMC_SD_PADS_NUM, |
1896 | fimc->vid_cap.sd_pads, 0); | 1895 | fimc->vid_cap.sd_pads); |
1897 | if (ret) | 1896 | if (ret) |
1898 | return ret; | 1897 | return ret; |
1899 | 1898 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index 0dd22ec66694..bf9261eb57a1 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c | |||
@@ -287,7 +287,7 @@ static int isp_video_open(struct file *file) | |||
287 | goto rel_fh; | 287 | goto rel_fh; |
288 | 288 | ||
289 | if (v4l2_fh_is_singular_file(file)) { | 289 | if (v4l2_fh_is_singular_file(file)) { |
290 | mutex_lock(&me->parent->graph_mutex); | 290 | mutex_lock(&me->graph_obj.mdev->graph_mutex); |
291 | 291 | ||
292 | ret = fimc_pipeline_call(ve, open, me, true); | 292 | ret = fimc_pipeline_call(ve, open, me, true); |
293 | 293 | ||
@@ -295,7 +295,7 @@ static int isp_video_open(struct file *file) | |||
295 | if (ret == 0) | 295 | if (ret == 0) |
296 | me->use_count++; | 296 | me->use_count++; |
297 | 297 | ||
298 | mutex_unlock(&me->parent->graph_mutex); | 298 | mutex_unlock(&me->graph_obj.mdev->graph_mutex); |
299 | } | 299 | } |
300 | if (!ret) | 300 | if (!ret) |
301 | goto unlock; | 301 | goto unlock; |
@@ -311,7 +311,7 @@ static int isp_video_release(struct file *file) | |||
311 | struct fimc_isp *isp = video_drvdata(file); | 311 | struct fimc_isp *isp = video_drvdata(file); |
312 | struct fimc_is_video *ivc = &isp->video_capture; | 312 | struct fimc_is_video *ivc = &isp->video_capture; |
313 | struct media_entity *entity = &ivc->ve.vdev.entity; | 313 | struct media_entity *entity = &ivc->ve.vdev.entity; |
314 | struct media_device *mdev = entity->parent; | 314 | struct media_device *mdev = entity->graph_obj.mdev; |
315 | 315 | ||
316 | mutex_lock(&isp->video_lock); | 316 | mutex_lock(&isp->video_lock); |
317 | 317 | ||
@@ -466,8 +466,7 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp) | |||
466 | 466 | ||
467 | /* Retrieve format at the source pad */ | 467 | /* Retrieve format at the source pad */ |
468 | pad = media_entity_remote_pad(pad); | 468 | pad = media_entity_remote_pad(pad); |
469 | if (pad == NULL || | 469 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
470 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
471 | break; | 470 | break; |
472 | 471 | ||
473 | sd = media_entity_to_v4l2_subdev(pad->entity); | 472 | sd = media_entity_to_v4l2_subdev(pad->entity); |
@@ -617,7 +616,7 @@ int fimc_isp_video_device_register(struct fimc_isp *isp, | |||
617 | vdev->lock = &isp->video_lock; | 616 | vdev->lock = &isp->video_lock; |
618 | 617 | ||
619 | iv->pad.flags = MEDIA_PAD_FL_SINK; | 618 | iv->pad.flags = MEDIA_PAD_FL_SINK; |
620 | ret = media_entity_init(&vdev->entity, 1, &iv->pad, 0); | 619 | ret = media_entity_pads_init(&vdev->entity, 1, &iv->pad); |
621 | if (ret < 0) | 620 | if (ret < 0) |
622 | return ret; | 621 | return ret; |
623 | 622 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index 5d78f5716f3b..293b807020c4 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c | |||
@@ -708,8 +708,8 @@ int fimc_isp_subdev_create(struct fimc_isp *isp) | |||
708 | isp->subdev_pads[FIMC_ISP_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; | 708 | isp->subdev_pads[FIMC_ISP_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; |
709 | isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_FIFO].flags = MEDIA_PAD_FL_SOURCE; | 709 | isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_FIFO].flags = MEDIA_PAD_FL_SOURCE; |
710 | isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_DMA].flags = MEDIA_PAD_FL_SOURCE; | 710 | isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_DMA].flags = MEDIA_PAD_FL_SOURCE; |
711 | ret = media_entity_init(&sd->entity, FIMC_ISP_SD_PADS_NUM, | 711 | ret = media_entity_pads_init(&sd->entity, FIMC_ISP_SD_PADS_NUM, |
712 | isp->subdev_pads, 0); | 712 | isp->subdev_pads); |
713 | if (ret) | 713 | if (ret) |
714 | return ret; | 714 | return ret; |
715 | 715 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 639ee710499e..e85649147dc8 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c | |||
@@ -494,7 +494,7 @@ static int fimc_lite_open(struct file *file) | |||
494 | atomic_read(&fimc->out_path) != FIMC_IO_DMA) | 494 | atomic_read(&fimc->out_path) != FIMC_IO_DMA) |
495 | goto unlock; | 495 | goto unlock; |
496 | 496 | ||
497 | mutex_lock(&me->parent->graph_mutex); | 497 | mutex_lock(&me->graph_obj.mdev->graph_mutex); |
498 | 498 | ||
499 | ret = fimc_pipeline_call(&fimc->ve, open, me, true); | 499 | ret = fimc_pipeline_call(&fimc->ve, open, me, true); |
500 | 500 | ||
@@ -502,7 +502,7 @@ static int fimc_lite_open(struct file *file) | |||
502 | if (ret == 0) | 502 | if (ret == 0) |
503 | me->use_count++; | 503 | me->use_count++; |
504 | 504 | ||
505 | mutex_unlock(&me->parent->graph_mutex); | 505 | mutex_unlock(&me->graph_obj.mdev->graph_mutex); |
506 | 506 | ||
507 | if (!ret) { | 507 | if (!ret) { |
508 | fimc_lite_clear_event_counters(fimc); | 508 | fimc_lite_clear_event_counters(fimc); |
@@ -535,9 +535,9 @@ static int fimc_lite_release(struct file *file) | |||
535 | fimc_pipeline_call(&fimc->ve, close); | 535 | fimc_pipeline_call(&fimc->ve, close); |
536 | clear_bit(ST_FLITE_IN_USE, &fimc->state); | 536 | clear_bit(ST_FLITE_IN_USE, &fimc->state); |
537 | 537 | ||
538 | mutex_lock(&entity->parent->graph_mutex); | 538 | mutex_lock(&entity->graph_obj.mdev->graph_mutex); |
539 | entity->use_count--; | 539 | entity->use_count--; |
540 | mutex_unlock(&entity->parent->graph_mutex); | 540 | mutex_unlock(&entity->graph_obj.mdev->graph_mutex); |
541 | } | 541 | } |
542 | 542 | ||
543 | _vb2_fop_release(file, NULL); | 543 | _vb2_fop_release(file, NULL); |
@@ -808,8 +808,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc) | |||
808 | } | 808 | } |
809 | /* Retrieve format at the source pad */ | 809 | /* Retrieve format at the source pad */ |
810 | pad = media_entity_remote_pad(pad); | 810 | pad = media_entity_remote_pad(pad); |
811 | if (pad == NULL || | 811 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
812 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
813 | break; | 812 | break; |
814 | 813 | ||
815 | sd = media_entity_to_v4l2_subdev(pad->entity); | 814 | sd = media_entity_to_v4l2_subdev(pad->entity); |
@@ -982,7 +981,6 @@ static int fimc_lite_link_setup(struct media_entity *entity, | |||
982 | { | 981 | { |
983 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 982 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
984 | struct fimc_lite *fimc = v4l2_get_subdevdata(sd); | 983 | struct fimc_lite *fimc = v4l2_get_subdevdata(sd); |
985 | unsigned int remote_ent_type = media_entity_type(remote->entity); | ||
986 | int ret = 0; | 984 | int ret = 0; |
987 | 985 | ||
988 | if (WARN_ON(fimc == NULL)) | 986 | if (WARN_ON(fimc == NULL)) |
@@ -994,7 +992,7 @@ static int fimc_lite_link_setup(struct media_entity *entity, | |||
994 | 992 | ||
995 | switch (local->index) { | 993 | switch (local->index) { |
996 | case FLITE_SD_PAD_SINK: | 994 | case FLITE_SD_PAD_SINK: |
997 | if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) { | 995 | if (!is_media_entity_v4l2_subdev(remote->entity)) { |
998 | ret = -EINVAL; | 996 | ret = -EINVAL; |
999 | break; | 997 | break; |
1000 | } | 998 | } |
@@ -1012,7 +1010,7 @@ static int fimc_lite_link_setup(struct media_entity *entity, | |||
1012 | case FLITE_SD_PAD_SOURCE_DMA: | 1010 | case FLITE_SD_PAD_SOURCE_DMA: |
1013 | if (!(flags & MEDIA_LNK_FL_ENABLED)) | 1011 | if (!(flags & MEDIA_LNK_FL_ENABLED)) |
1014 | atomic_set(&fimc->out_path, FIMC_IO_NONE); | 1012 | atomic_set(&fimc->out_path, FIMC_IO_NONE); |
1015 | else if (remote_ent_type == MEDIA_ENT_T_DEVNODE) | 1013 | else if (is_media_entity_v4l2_io(remote->entity)) |
1016 | atomic_set(&fimc->out_path, FIMC_IO_DMA); | 1014 | atomic_set(&fimc->out_path, FIMC_IO_DMA); |
1017 | else | 1015 | else |
1018 | ret = -EINVAL; | 1016 | ret = -EINVAL; |
@@ -1021,7 +1019,7 @@ static int fimc_lite_link_setup(struct media_entity *entity, | |||
1021 | case FLITE_SD_PAD_SOURCE_ISP: | 1019 | case FLITE_SD_PAD_SOURCE_ISP: |
1022 | if (!(flags & MEDIA_LNK_FL_ENABLED)) | 1020 | if (!(flags & MEDIA_LNK_FL_ENABLED)) |
1023 | atomic_set(&fimc->out_path, FIMC_IO_NONE); | 1021 | atomic_set(&fimc->out_path, FIMC_IO_NONE); |
1024 | else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV) | 1022 | else if (is_media_entity_v4l2_subdev(remote->entity)) |
1025 | atomic_set(&fimc->out_path, FIMC_IO_ISP); | 1023 | atomic_set(&fimc->out_path, FIMC_IO_ISP); |
1026 | else | 1024 | else |
1027 | ret = -EINVAL; | 1025 | ret = -EINVAL; |
@@ -1316,7 +1314,7 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) | |||
1316 | return ret; | 1314 | return ret; |
1317 | 1315 | ||
1318 | fimc->vd_pad.flags = MEDIA_PAD_FL_SINK; | 1316 | fimc->vd_pad.flags = MEDIA_PAD_FL_SINK; |
1319 | ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0); | 1317 | ret = media_entity_pads_init(&vfd->entity, 1, &fimc->vd_pad); |
1320 | if (ret < 0) | 1318 | if (ret < 0) |
1321 | return ret; | 1319 | return ret; |
1322 | 1320 | ||
@@ -1430,8 +1428,8 @@ static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc) | |||
1430 | fimc->subdev_pads[FLITE_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; | 1428 | fimc->subdev_pads[FLITE_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; |
1431 | fimc->subdev_pads[FLITE_SD_PAD_SOURCE_DMA].flags = MEDIA_PAD_FL_SOURCE; | 1429 | fimc->subdev_pads[FLITE_SD_PAD_SOURCE_DMA].flags = MEDIA_PAD_FL_SOURCE; |
1432 | fimc->subdev_pads[FLITE_SD_PAD_SOURCE_ISP].flags = MEDIA_PAD_FL_SOURCE; | 1430 | fimc->subdev_pads[FLITE_SD_PAD_SOURCE_ISP].flags = MEDIA_PAD_FL_SOURCE; |
1433 | ret = media_entity_init(&sd->entity, FLITE_SD_PADS_NUM, | 1431 | ret = media_entity_pads_init(&sd->entity, FLITE_SD_PADS_NUM, |
1434 | fimc->subdev_pads, 0); | 1432 | fimc->subdev_pads); |
1435 | if (ret) | 1433 | if (ret) |
1436 | return ret; | 1434 | return ret; |
1437 | 1435 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index 5aa857c7b631..55ec4c99d484 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c | |||
@@ -739,7 +739,7 @@ int fimc_register_m2m_device(struct fimc_dev *fimc, | |||
739 | return PTR_ERR(fimc->m2m.m2m_dev); | 739 | return PTR_ERR(fimc->m2m.m2m_dev); |
740 | } | 740 | } |
741 | 741 | ||
742 | ret = media_entity_init(&vfd->entity, 0, NULL, 0); | 742 | ret = media_entity_pads_init(&vfd->entity, 0, NULL); |
743 | if (ret) | 743 | if (ret) |
744 | goto err_me; | 744 | goto err_me; |
745 | 745 | ||
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 9481ce3201a2..f3b2dd30ec77 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c | |||
@@ -88,8 +88,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, | |||
88 | break; | 88 | break; |
89 | } | 89 | } |
90 | 90 | ||
91 | if (pad == NULL || | 91 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
92 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
93 | break; | 92 | break; |
94 | sd = media_entity_to_v4l2_subdev(pad->entity); | 93 | sd = media_entity_to_v4l2_subdev(pad->entity); |
95 | 94 | ||
@@ -729,7 +728,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, | |||
729 | flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0; | 728 | flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0; |
730 | 729 | ||
731 | sink = &fmd->fimc[i]->vid_cap.subdev.entity; | 730 | sink = &fmd->fimc[i]->vid_cap.subdev.entity; |
732 | ret = media_entity_create_link(source, pad, sink, | 731 | ret = media_create_pad_link(source, pad, sink, |
733 | FIMC_SD_PAD_SINK_CAM, flags); | 732 | FIMC_SD_PAD_SINK_CAM, flags); |
734 | if (ret) | 733 | if (ret) |
735 | return ret; | 734 | return ret; |
@@ -749,7 +748,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, | |||
749 | continue; | 748 | continue; |
750 | 749 | ||
751 | sink = &fmd->fimc_lite[i]->subdev.entity; | 750 | sink = &fmd->fimc_lite[i]->subdev.entity; |
752 | ret = media_entity_create_link(source, pad, sink, | 751 | ret = media_create_pad_link(source, pad, sink, |
753 | FLITE_SD_PAD_SINK, 0); | 752 | FLITE_SD_PAD_SINK, 0); |
754 | if (ret) | 753 | if (ret) |
755 | return ret; | 754 | return ret; |
@@ -781,13 +780,13 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) | |||
781 | source = &fimc->subdev.entity; | 780 | source = &fimc->subdev.entity; |
782 | sink = &fimc->ve.vdev.entity; | 781 | sink = &fimc->ve.vdev.entity; |
783 | /* FIMC-LITE's subdev and video node */ | 782 | /* FIMC-LITE's subdev and video node */ |
784 | ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_DMA, | 783 | ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA, |
785 | sink, 0, 0); | 784 | sink, 0, 0); |
786 | if (ret) | 785 | if (ret) |
787 | break; | 786 | break; |
788 | /* Link from FIMC-LITE to IS-ISP subdev */ | 787 | /* Link from FIMC-LITE to IS-ISP subdev */ |
789 | sink = &fmd->fimc_is->isp.subdev.entity; | 788 | sink = &fmd->fimc_is->isp.subdev.entity; |
790 | ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_ISP, | 789 | ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP, |
791 | sink, 0, 0); | 790 | sink, 0, 0); |
792 | if (ret) | 791 | if (ret) |
793 | break; | 792 | break; |
@@ -811,7 +810,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd) | |||
811 | 810 | ||
812 | /* Link from FIMC-IS-ISP subdev to FIMC */ | 811 | /* Link from FIMC-IS-ISP subdev to FIMC */ |
813 | sink = &fmd->fimc[i]->vid_cap.subdev.entity; | 812 | sink = &fmd->fimc[i]->vid_cap.subdev.entity; |
814 | ret = media_entity_create_link(source, FIMC_ISP_SD_PAD_SRC_FIFO, | 813 | ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO, |
815 | sink, FIMC_SD_PAD_SINK_FIFO, 0); | 814 | sink, FIMC_SD_PAD_SINK_FIFO, 0); |
816 | if (ret) | 815 | if (ret) |
817 | return ret; | 816 | return ret; |
@@ -824,7 +823,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd) | |||
824 | if (sink->num_pads == 0) | 823 | if (sink->num_pads == 0) |
825 | return 0; | 824 | return 0; |
826 | 825 | ||
827 | return media_entity_create_link(source, FIMC_ISP_SD_PAD_SRC_DMA, | 826 | return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA, |
828 | sink, 0, 0); | 827 | sink, 0, 0); |
829 | } | 828 | } |
830 | 829 | ||
@@ -873,7 +872,7 @@ static int fimc_md_create_links(struct fimc_md *fmd) | |||
873 | return -EINVAL; | 872 | return -EINVAL; |
874 | 873 | ||
875 | pad = sensor->entity.num_pads - 1; | 874 | pad = sensor->entity.num_pads - 1; |
876 | ret = media_entity_create_link(&sensor->entity, pad, | 875 | ret = media_create_pad_link(&sensor->entity, pad, |
877 | &csis->entity, CSIS_PAD_SINK, | 876 | &csis->entity, CSIS_PAD_SINK, |
878 | MEDIA_LNK_FL_IMMUTABLE | | 877 | MEDIA_LNK_FL_IMMUTABLE | |
879 | MEDIA_LNK_FL_ENABLED); | 878 | MEDIA_LNK_FL_ENABLED); |
@@ -927,7 +926,7 @@ static int fimc_md_create_links(struct fimc_md *fmd) | |||
927 | source = &fmd->fimc[i]->vid_cap.subdev.entity; | 926 | source = &fmd->fimc[i]->vid_cap.subdev.entity; |
928 | sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity; | 927 | sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity; |
929 | 928 | ||
930 | ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, | 929 | ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE, |
931 | sink, 0, flags); | 930 | sink, 0, flags); |
932 | if (ret) | 931 | if (ret) |
933 | break; | 932 | break; |
@@ -1046,11 +1045,11 @@ static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable) | |||
1046 | return ret; | 1045 | return ret; |
1047 | } | 1046 | } |
1048 | 1047 | ||
1049 | /* Locking: called with entity->parent->graph_mutex mutex held. */ | 1048 | /* Locking: called with entity->graph_obj.mdev->graph_mutex mutex held. */ |
1050 | static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable) | 1049 | static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable, |
1050 | struct media_entity_graph *graph) | ||
1051 | { | 1051 | { |
1052 | struct media_entity *entity_err = entity; | 1052 | struct media_entity *entity_err = entity; |
1053 | struct media_entity_graph graph; | ||
1054 | int ret; | 1053 | int ret; |
1055 | 1054 | ||
1056 | /* | 1055 | /* |
@@ -1059,10 +1058,10 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable) | |||
1059 | * through active links. This is needed as we cannot power on/off the | 1058 | * through active links. This is needed as we cannot power on/off the |
1060 | * subdevs in random order. | 1059 | * subdevs in random order. |
1061 | */ | 1060 | */ |
1062 | media_entity_graph_walk_start(&graph, entity); | 1061 | media_entity_graph_walk_start(graph, entity); |
1063 | 1062 | ||
1064 | while ((entity = media_entity_graph_walk_next(&graph))) { | 1063 | while ((entity = media_entity_graph_walk_next(graph))) { |
1065 | if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) | 1064 | if (!is_media_entity_v4l2_io(entity)) |
1066 | continue; | 1065 | continue; |
1067 | 1066 | ||
1068 | ret = __fimc_md_modify_pipeline(entity, enable); | 1067 | ret = __fimc_md_modify_pipeline(entity, enable); |
@@ -1072,11 +1071,12 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable) | |||
1072 | } | 1071 | } |
1073 | 1072 | ||
1074 | return 0; | 1073 | return 0; |
1075 | err: | ||
1076 | media_entity_graph_walk_start(&graph, entity_err); | ||
1077 | 1074 | ||
1078 | while ((entity_err = media_entity_graph_walk_next(&graph))) { | 1075 | err: |
1079 | if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE) | 1076 | media_entity_graph_walk_start(graph, entity_err); |
1077 | |||
1078 | while ((entity_err = media_entity_graph_walk_next(graph))) { | ||
1079 | if (!is_media_entity_v4l2_io(entity_err)) | ||
1080 | continue; | 1080 | continue; |
1081 | 1081 | ||
1082 | __fimc_md_modify_pipeline(entity_err, !enable); | 1082 | __fimc_md_modify_pipeline(entity_err, !enable); |
@@ -1091,21 +1091,29 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable) | |||
1091 | static int fimc_md_link_notify(struct media_link *link, unsigned int flags, | 1091 | static int fimc_md_link_notify(struct media_link *link, unsigned int flags, |
1092 | unsigned int notification) | 1092 | unsigned int notification) |
1093 | { | 1093 | { |
1094 | struct media_entity_graph *graph = | ||
1095 | &container_of(link->graph_obj.mdev, struct fimc_md, | ||
1096 | media_dev)->link_setup_graph; | ||
1094 | struct media_entity *sink = link->sink->entity; | 1097 | struct media_entity *sink = link->sink->entity; |
1095 | int ret = 0; | 1098 | int ret = 0; |
1096 | 1099 | ||
1097 | /* Before link disconnection */ | 1100 | /* Before link disconnection */ |
1098 | if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) { | 1101 | if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) { |
1102 | ret = media_entity_graph_walk_init(graph, | ||
1103 | link->graph_obj.mdev); | ||
1104 | if (ret) | ||
1105 | return ret; | ||
1099 | if (!(flags & MEDIA_LNK_FL_ENABLED)) | 1106 | if (!(flags & MEDIA_LNK_FL_ENABLED)) |
1100 | ret = __fimc_md_modify_pipelines(sink, false); | 1107 | ret = __fimc_md_modify_pipelines(sink, false, graph); |
1101 | #if 0 | 1108 | #if 0 |
1102 | else | 1109 | else |
1103 | /* TODO: Link state change validation */ | 1110 | /* TODO: Link state change validation */ |
1104 | #endif | 1111 | #endif |
1105 | /* After link activation */ | 1112 | /* After link activation */ |
1106 | } else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && | 1113 | } else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH) { |
1107 | (link->flags & MEDIA_LNK_FL_ENABLED)) { | 1114 | if (link->flags & MEDIA_LNK_FL_ENABLED) |
1108 | ret = __fimc_md_modify_pipelines(sink, true); | 1115 | ret = __fimc_md_modify_pipelines(sink, true, graph); |
1116 | media_entity_graph_walk_cleanup(graph); | ||
1109 | } | 1117 | } |
1110 | 1118 | ||
1111 | return ret ? -EPIPE : 0; | 1119 | return ret ? -EPIPE : 0; |
@@ -1314,7 +1322,10 @@ static int subdev_notifier_complete(struct v4l2_async_notifier *notifier) | |||
1314 | ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); | 1322 | ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); |
1315 | unlock: | 1323 | unlock: |
1316 | mutex_unlock(&fmd->media_dev.graph_mutex); | 1324 | mutex_unlock(&fmd->media_dev.graph_mutex); |
1317 | return ret; | 1325 | if (ret < 0) |
1326 | return ret; | ||
1327 | |||
1328 | return media_device_register(&fmd->media_dev); | ||
1318 | } | 1329 | } |
1319 | 1330 | ||
1320 | static int fimc_md_probe(struct platform_device *pdev) | 1331 | static int fimc_md_probe(struct platform_device *pdev) |
@@ -1345,18 +1356,14 @@ static int fimc_md_probe(struct platform_device *pdev) | |||
1345 | fmd->use_isp = fimc_md_is_isp_available(dev->of_node); | 1356 | fmd->use_isp = fimc_md_is_isp_available(dev->of_node); |
1346 | fmd->user_subdev_api = true; | 1357 | fmd->user_subdev_api = true; |
1347 | 1358 | ||
1359 | media_device_init(&fmd->media_dev); | ||
1360 | |||
1348 | ret = v4l2_device_register(dev, &fmd->v4l2_dev); | 1361 | ret = v4l2_device_register(dev, &fmd->v4l2_dev); |
1349 | if (ret < 0) { | 1362 | if (ret < 0) { |
1350 | v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); | 1363 | v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); |
1351 | return ret; | 1364 | return ret; |
1352 | } | 1365 | } |
1353 | 1366 | ||
1354 | ret = media_device_register(&fmd->media_dev); | ||
1355 | if (ret < 0) { | ||
1356 | v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret); | ||
1357 | goto err_v4l2_dev; | ||
1358 | } | ||
1359 | |||
1360 | ret = fimc_md_get_clocks(fmd); | 1367 | ret = fimc_md_get_clocks(fmd); |
1361 | if (ret) | 1368 | if (ret) |
1362 | goto err_md; | 1369 | goto err_md; |
@@ -1425,8 +1432,7 @@ err_clk: | |||
1425 | err_m_ent: | 1432 | err_m_ent: |
1426 | fimc_md_unregister_entities(fmd); | 1433 | fimc_md_unregister_entities(fmd); |
1427 | err_md: | 1434 | err_md: |
1428 | media_device_unregister(&fmd->media_dev); | 1435 | media_device_cleanup(&fmd->media_dev); |
1429 | err_v4l2_dev: | ||
1430 | v4l2_device_unregister(&fmd->v4l2_dev); | 1436 | v4l2_device_unregister(&fmd->v4l2_dev); |
1431 | return ret; | 1437 | return ret; |
1432 | } | 1438 | } |
@@ -1446,6 +1452,7 @@ static int fimc_md_remove(struct platform_device *pdev) | |||
1446 | fimc_md_unregister_entities(fmd); | 1452 | fimc_md_unregister_entities(fmd); |
1447 | fimc_md_pipelines_free(fmd); | 1453 | fimc_md_pipelines_free(fmd); |
1448 | media_device_unregister(&fmd->media_dev); | 1454 | media_device_unregister(&fmd->media_dev); |
1455 | media_device_cleanup(&fmd->media_dev); | ||
1449 | fimc_md_put_clocks(fmd); | 1456 | fimc_md_put_clocks(fmd); |
1450 | 1457 | ||
1451 | return 0; | 1458 | return 0; |
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h index 93a96126929b..ed122cb2dd74 100644 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ b/drivers/media/platform/exynos4-is/media-dev.h | |||
@@ -154,6 +154,7 @@ struct fimc_md { | |||
154 | bool user_subdev_api; | 154 | bool user_subdev_api; |
155 | spinlock_t slock; | 155 | spinlock_t slock; |
156 | struct list_head pipelines; | 156 | struct list_head pipelines; |
157 | struct media_entity_graph link_setup_graph; | ||
157 | }; | 158 | }; |
158 | 159 | ||
159 | static inline | 160 | static inline |
@@ -164,8 +165,8 @@ struct fimc_sensor_info *source_to_sensor_info(struct fimc_source_info *si) | |||
164 | 165 | ||
165 | static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me) | 166 | static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me) |
166 | { | 167 | { |
167 | return me->parent == NULL ? NULL : | 168 | return me->graph_obj.mdev == NULL ? NULL : |
168 | container_of(me->parent, struct fimc_md, media_dev); | 169 | container_of(me->graph_obj.mdev, struct fimc_md, media_dev); |
169 | } | 170 | } |
170 | 171 | ||
171 | static inline struct fimc_md *notifier_to_fimc_md(struct v4l2_async_notifier *n) | 172 | static inline struct fimc_md *notifier_to_fimc_md(struct v4l2_async_notifier *n) |
@@ -175,12 +176,12 @@ static inline struct fimc_md *notifier_to_fimc_md(struct v4l2_async_notifier *n) | |||
175 | 176 | ||
176 | static inline void fimc_md_graph_lock(struct exynos_video_entity *ve) | 177 | static inline void fimc_md_graph_lock(struct exynos_video_entity *ve) |
177 | { | 178 | { |
178 | mutex_lock(&ve->vdev.entity.parent->graph_mutex); | 179 | mutex_lock(&ve->vdev.entity.graph_obj.mdev->graph_mutex); |
179 | } | 180 | } |
180 | 181 | ||
181 | static inline void fimc_md_graph_unlock(struct exynos_video_entity *ve) | 182 | static inline void fimc_md_graph_unlock(struct exynos_video_entity *ve) |
182 | { | 183 | { |
183 | mutex_unlock(&ve->vdev.entity.parent->graph_mutex); | 184 | mutex_unlock(&ve->vdev.entity.graph_obj.mdev->graph_mutex); |
184 | } | 185 | } |
185 | 186 | ||
186 | int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); | 187 | int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); |
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index ff5dabf24694..ac5e50e595be 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c | |||
@@ -866,8 +866,8 @@ static int s5pcsis_probe(struct platform_device *pdev) | |||
866 | 866 | ||
867 | state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK; | 867 | state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK; |
868 | state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; | 868 | state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; |
869 | ret = media_entity_init(&state->sd.entity, | 869 | ret = media_entity_pads_init(&state->sd.entity, |
870 | CSIS_PADS_NUM, state->pads, 0); | 870 | CSIS_PADS_NUM, state->pads); |
871 | if (ret < 0) | 871 | if (ret < 0) |
872 | goto e_clkdis; | 872 | goto e_clkdis; |
873 | 873 | ||
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 56e683b19a73..0bcfa553c1aa 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c | |||
@@ -683,15 +683,15 @@ static irqreturn_t isp_isr(int irq, void *_isp) | |||
683 | * | 683 | * |
684 | * Return the total number of users of all video device nodes in the pipeline. | 684 | * Return the total number of users of all video device nodes in the pipeline. |
685 | */ | 685 | */ |
686 | static int isp_pipeline_pm_use_count(struct media_entity *entity) | 686 | static int isp_pipeline_pm_use_count(struct media_entity *entity, |
687 | struct media_entity_graph *graph) | ||
687 | { | 688 | { |
688 | struct media_entity_graph graph; | ||
689 | int use = 0; | 689 | int use = 0; |
690 | 690 | ||
691 | media_entity_graph_walk_start(&graph, entity); | 691 | media_entity_graph_walk_start(graph, entity); |
692 | 692 | ||
693 | while ((entity = media_entity_graph_walk_next(&graph))) { | 693 | while ((entity = media_entity_graph_walk_next(graph))) { |
694 | if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) | 694 | if (is_media_entity_v4l2_io(entity)) |
695 | use += entity->use_count; | 695 | use += entity->use_count; |
696 | } | 696 | } |
697 | 697 | ||
@@ -714,7 +714,7 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change) | |||
714 | struct v4l2_subdev *subdev; | 714 | struct v4l2_subdev *subdev; |
715 | int ret; | 715 | int ret; |
716 | 716 | ||
717 | subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV | 717 | subdev = is_media_entity_v4l2_subdev(entity) |
718 | ? media_entity_to_v4l2_subdev(entity) : NULL; | 718 | ? media_entity_to_v4l2_subdev(entity) : NULL; |
719 | 719 | ||
720 | if (entity->use_count == 0 && change > 0 && subdev != NULL) { | 720 | if (entity->use_count == 0 && change > 0 && subdev != NULL) { |
@@ -742,29 +742,29 @@ static int isp_pipeline_pm_power_one(struct media_entity *entity, int change) | |||
742 | * | 742 | * |
743 | * Return 0 on success or a negative error code on failure. | 743 | * Return 0 on success or a negative error code on failure. |
744 | */ | 744 | */ |
745 | static int isp_pipeline_pm_power(struct media_entity *entity, int change) | 745 | static int isp_pipeline_pm_power(struct media_entity *entity, int change, |
746 | struct media_entity_graph *graph) | ||
746 | { | 747 | { |
747 | struct media_entity_graph graph; | ||
748 | struct media_entity *first = entity; | 748 | struct media_entity *first = entity; |
749 | int ret = 0; | 749 | int ret = 0; |
750 | 750 | ||
751 | if (!change) | 751 | if (!change) |
752 | return 0; | 752 | return 0; |
753 | 753 | ||
754 | media_entity_graph_walk_start(&graph, entity); | 754 | media_entity_graph_walk_start(graph, entity); |
755 | 755 | ||
756 | while (!ret && (entity = media_entity_graph_walk_next(&graph))) | 756 | while (!ret && (entity = media_entity_graph_walk_next(graph))) |
757 | if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) | 757 | if (is_media_entity_v4l2_subdev(entity)) |
758 | ret = isp_pipeline_pm_power_one(entity, change); | 758 | ret = isp_pipeline_pm_power_one(entity, change); |
759 | 759 | ||
760 | if (!ret) | 760 | if (!ret) |
761 | return 0; | 761 | return ret; |
762 | 762 | ||
763 | media_entity_graph_walk_start(&graph, first); | 763 | media_entity_graph_walk_start(graph, first); |
764 | 764 | ||
765 | while ((first = media_entity_graph_walk_next(&graph)) | 765 | while ((first = media_entity_graph_walk_next(graph)) |
766 | && first != entity) | 766 | && first != entity) |
767 | if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE) | 767 | if (is_media_entity_v4l2_subdev(first)) |
768 | isp_pipeline_pm_power_one(first, -change); | 768 | isp_pipeline_pm_power_one(first, -change); |
769 | 769 | ||
770 | return ret; | 770 | return ret; |
@@ -782,23 +782,24 @@ static int isp_pipeline_pm_power(struct media_entity *entity, int change) | |||
782 | * off is assumed to never fail. No failure can occur when the use parameter is | 782 | * off is assumed to never fail. No failure can occur when the use parameter is |
783 | * set to 0. | 783 | * set to 0. |
784 | */ | 784 | */ |
785 | int omap3isp_pipeline_pm_use(struct media_entity *entity, int use) | 785 | int omap3isp_pipeline_pm_use(struct media_entity *entity, int use, |
786 | struct media_entity_graph *graph) | ||
786 | { | 787 | { |
787 | int change = use ? 1 : -1; | 788 | int change = use ? 1 : -1; |
788 | int ret; | 789 | int ret; |
789 | 790 | ||
790 | mutex_lock(&entity->parent->graph_mutex); | 791 | mutex_lock(&entity->graph_obj.mdev->graph_mutex); |
791 | 792 | ||
792 | /* Apply use count to node. */ | 793 | /* Apply use count to node. */ |
793 | entity->use_count += change; | 794 | entity->use_count += change; |
794 | WARN_ON(entity->use_count < 0); | 795 | WARN_ON(entity->use_count < 0); |
795 | 796 | ||
796 | /* Apply power change to connected non-nodes. */ | 797 | /* Apply power change to connected non-nodes. */ |
797 | ret = isp_pipeline_pm_power(entity, change); | 798 | ret = isp_pipeline_pm_power(entity, change, graph); |
798 | if (ret < 0) | 799 | if (ret < 0) |
799 | entity->use_count -= change; | 800 | entity->use_count -= change; |
800 | 801 | ||
801 | mutex_unlock(&entity->parent->graph_mutex); | 802 | mutex_unlock(&entity->graph_obj.mdev->graph_mutex); |
802 | 803 | ||
803 | return ret; | 804 | return ret; |
804 | } | 805 | } |
@@ -820,35 +821,49 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use) | |||
820 | static int isp_pipeline_link_notify(struct media_link *link, u32 flags, | 821 | static int isp_pipeline_link_notify(struct media_link *link, u32 flags, |
821 | unsigned int notification) | 822 | unsigned int notification) |
822 | { | 823 | { |
824 | struct media_entity_graph *graph = | ||
825 | &container_of(link->graph_obj.mdev, struct isp_device, | ||
826 | media_dev)->pm_count_graph; | ||
823 | struct media_entity *source = link->source->entity; | 827 | struct media_entity *source = link->source->entity; |
824 | struct media_entity *sink = link->sink->entity; | 828 | struct media_entity *sink = link->sink->entity; |
825 | int source_use = isp_pipeline_pm_use_count(source); | 829 | int source_use; |
826 | int sink_use = isp_pipeline_pm_use_count(sink); | 830 | int sink_use; |
827 | int ret; | 831 | int ret = 0; |
832 | |||
833 | if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) { | ||
834 | ret = media_entity_graph_walk_init(graph, | ||
835 | link->graph_obj.mdev); | ||
836 | if (ret) | ||
837 | return ret; | ||
838 | } | ||
839 | |||
840 | source_use = isp_pipeline_pm_use_count(source, graph); | ||
841 | sink_use = isp_pipeline_pm_use_count(sink, graph); | ||
828 | 842 | ||
829 | if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && | 843 | if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && |
830 | !(flags & MEDIA_LNK_FL_ENABLED)) { | 844 | !(flags & MEDIA_LNK_FL_ENABLED)) { |
831 | /* Powering off entities is assumed to never fail. */ | 845 | /* Powering off entities is assumed to never fail. */ |
832 | isp_pipeline_pm_power(source, -sink_use); | 846 | isp_pipeline_pm_power(source, -sink_use, graph); |
833 | isp_pipeline_pm_power(sink, -source_use); | 847 | isp_pipeline_pm_power(sink, -source_use, graph); |
834 | return 0; | 848 | return 0; |
835 | } | 849 | } |
836 | 850 | ||
837 | if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH && | 851 | if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH && |
838 | (flags & MEDIA_LNK_FL_ENABLED)) { | 852 | (flags & MEDIA_LNK_FL_ENABLED)) { |
839 | 853 | ||
840 | ret = isp_pipeline_pm_power(source, sink_use); | 854 | ret = isp_pipeline_pm_power(source, sink_use, graph); |
841 | if (ret < 0) | 855 | if (ret < 0) |
842 | return ret; | 856 | return ret; |
843 | 857 | ||
844 | ret = isp_pipeline_pm_power(sink, source_use); | 858 | ret = isp_pipeline_pm_power(sink, source_use, graph); |
845 | if (ret < 0) | 859 | if (ret < 0) |
846 | isp_pipeline_pm_power(source, -sink_use); | 860 | isp_pipeline_pm_power(source, -sink_use, graph); |
847 | |||
848 | return ret; | ||
849 | } | 861 | } |
850 | 862 | ||
851 | return 0; | 863 | if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH) |
864 | media_entity_graph_walk_cleanup(graph); | ||
865 | |||
866 | return ret; | ||
852 | } | 867 | } |
853 | 868 | ||
854 | /* ----------------------------------------------------------------------------- | 869 | /* ----------------------------------------------------------------------------- |
@@ -881,7 +896,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe, | |||
881 | * starting entities if the pipeline won't start anyway (those entities | 896 | * starting entities if the pipeline won't start anyway (those entities |
882 | * would then likely fail to stop, making the problem worse). | 897 | * would then likely fail to stop, making the problem worse). |
883 | */ | 898 | */ |
884 | if (pipe->entities & isp->crashed) | 899 | if (media_entity_enum_intersects(&pipe->ent_enum, &isp->crashed)) |
885 | return -EIO; | 900 | return -EIO; |
886 | 901 | ||
887 | spin_lock_irqsave(&pipe->lock, flags); | 902 | spin_lock_irqsave(&pipe->lock, flags); |
@@ -897,8 +912,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe, | |||
897 | break; | 912 | break; |
898 | 913 | ||
899 | pad = media_entity_remote_pad(pad); | 914 | pad = media_entity_remote_pad(pad); |
900 | if (pad == NULL || | 915 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
901 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
902 | break; | 916 | break; |
903 | 917 | ||
904 | entity = pad->entity; | 918 | entity = pad->entity; |
@@ -987,8 +1001,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe) | |||
987 | break; | 1001 | break; |
988 | 1002 | ||
989 | pad = media_entity_remote_pad(pad); | 1003 | pad = media_entity_remote_pad(pad); |
990 | if (pad == NULL || | 1004 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
991 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
992 | break; | 1005 | break; |
993 | 1006 | ||
994 | entity = pad->entity; | 1007 | entity = pad->entity; |
@@ -1028,7 +1041,8 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe) | |||
1028 | dev_info(isp->dev, "Unable to stop %s\n", subdev->name); | 1041 | dev_info(isp->dev, "Unable to stop %s\n", subdev->name); |
1029 | isp->stop_failure = true; | 1042 | isp->stop_failure = true; |
1030 | if (subdev == &isp->isp_prev.subdev) | 1043 | if (subdev == &isp->isp_prev.subdev) |
1031 | isp->crashed |= 1U << subdev->entity.id; | 1044 | media_entity_enum_set(&isp->crashed, |
1045 | &subdev->entity); | ||
1032 | failure = -ETIMEDOUT; | 1046 | failure = -ETIMEDOUT; |
1033 | } | 1047 | } |
1034 | } | 1048 | } |
@@ -1234,7 +1248,7 @@ static int isp_reset(struct isp_device *isp) | |||
1234 | } | 1248 | } |
1235 | 1249 | ||
1236 | isp->stop_failure = false; | 1250 | isp->stop_failure = false; |
1237 | isp->crashed = 0; | 1251 | media_entity_enum_zero(&isp->crashed); |
1238 | return 0; | 1252 | return 0; |
1239 | } | 1253 | } |
1240 | 1254 | ||
@@ -1645,7 +1659,8 @@ static void __omap3isp_put(struct isp_device *isp, bool save_ctx) | |||
1645 | /* Reset the ISP if an entity has failed to stop. This is the | 1659 | /* Reset the ISP if an entity has failed to stop. This is the |
1646 | * only way to recover from such conditions. | 1660 | * only way to recover from such conditions. |
1647 | */ | 1661 | */ |
1648 | if (isp->crashed || isp->stop_failure) | 1662 | if (!media_entity_enum_empty(&isp->crashed) || |
1663 | isp->stop_failure) | ||
1649 | isp_reset(isp); | 1664 | isp_reset(isp); |
1650 | isp_disable_clocks(isp); | 1665 | isp_disable_clocks(isp); |
1651 | } | 1666 | } |
@@ -1792,6 +1807,7 @@ static void isp_unregister_entities(struct isp_device *isp) | |||
1792 | 1807 | ||
1793 | v4l2_device_unregister(&isp->v4l2_dev); | 1808 | v4l2_device_unregister(&isp->v4l2_dev); |
1794 | media_device_unregister(&isp->media_dev); | 1809 | media_device_unregister(&isp->media_dev); |
1810 | media_device_cleanup(&isp->media_dev); | ||
1795 | } | 1811 | } |
1796 | 1812 | ||
1797 | static int isp_link_entity( | 1813 | static int isp_link_entity( |
@@ -1862,7 +1878,7 @@ static int isp_link_entity( | |||
1862 | return -EINVAL; | 1878 | return -EINVAL; |
1863 | } | 1879 | } |
1864 | 1880 | ||
1865 | return media_entity_create_link(entity, i, input, pad, flags); | 1881 | return media_create_pad_link(entity, i, input, pad, flags); |
1866 | } | 1882 | } |
1867 | 1883 | ||
1868 | static int isp_register_entities(struct isp_device *isp) | 1884 | static int isp_register_entities(struct isp_device *isp) |
@@ -1874,12 +1890,7 @@ static int isp_register_entities(struct isp_device *isp) | |||
1874 | sizeof(isp->media_dev.model)); | 1890 | sizeof(isp->media_dev.model)); |
1875 | isp->media_dev.hw_revision = isp->revision; | 1891 | isp->media_dev.hw_revision = isp->revision; |
1876 | isp->media_dev.link_notify = isp_pipeline_link_notify; | 1892 | isp->media_dev.link_notify = isp_pipeline_link_notify; |
1877 | ret = media_device_register(&isp->media_dev); | 1893 | media_device_init(&isp->media_dev); |
1878 | if (ret < 0) { | ||
1879 | dev_err(isp->dev, "%s: Media device registration failed (%d)\n", | ||
1880 | __func__, ret); | ||
1881 | return ret; | ||
1882 | } | ||
1883 | 1894 | ||
1884 | isp->v4l2_dev.mdev = &isp->media_dev; | 1895 | isp->v4l2_dev.mdev = &isp->media_dev; |
1885 | ret = v4l2_device_register(isp->dev, &isp->v4l2_dev); | 1896 | ret = v4l2_device_register(isp->dev, &isp->v4l2_dev); |
@@ -1930,6 +1941,118 @@ done: | |||
1930 | return ret; | 1941 | return ret; |
1931 | } | 1942 | } |
1932 | 1943 | ||
1944 | /* | ||
1945 | * isp_create_links() - Create links for internal and external ISP entities | ||
1946 | * @isp : Pointer to ISP device | ||
1947 | * | ||
1948 | * This function creates all links between ISP internal and external entities. | ||
1949 | * | ||
1950 | * Return: A negative error code on failure or zero on success. Possible error | ||
1951 | * codes are those returned by media_create_pad_link(). | ||
1952 | */ | ||
1953 | static int isp_create_links(struct isp_device *isp) | ||
1954 | { | ||
1955 | int ret; | ||
1956 | |||
1957 | /* Create links between entities and video nodes. */ | ||
1958 | ret = media_create_pad_link( | ||
1959 | &isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE, | ||
1960 | &isp->isp_csi2a.video_out.video.entity, 0, 0); | ||
1961 | if (ret < 0) | ||
1962 | return ret; | ||
1963 | |||
1964 | ret = media_create_pad_link( | ||
1965 | &isp->isp_ccp2.video_in.video.entity, 0, | ||
1966 | &isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0); | ||
1967 | if (ret < 0) | ||
1968 | return ret; | ||
1969 | |||
1970 | ret = media_create_pad_link( | ||
1971 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF, | ||
1972 | &isp->isp_ccdc.video_out.video.entity, 0, 0); | ||
1973 | if (ret < 0) | ||
1974 | return ret; | ||
1975 | |||
1976 | ret = media_create_pad_link( | ||
1977 | &isp->isp_prev.video_in.video.entity, 0, | ||
1978 | &isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0); | ||
1979 | if (ret < 0) | ||
1980 | return ret; | ||
1981 | |||
1982 | ret = media_create_pad_link( | ||
1983 | &isp->isp_prev.subdev.entity, PREV_PAD_SOURCE, | ||
1984 | &isp->isp_prev.video_out.video.entity, 0, 0); | ||
1985 | if (ret < 0) | ||
1986 | return ret; | ||
1987 | |||
1988 | ret = media_create_pad_link( | ||
1989 | &isp->isp_res.video_in.video.entity, 0, | ||
1990 | &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0); | ||
1991 | if (ret < 0) | ||
1992 | return ret; | ||
1993 | |||
1994 | ret = media_create_pad_link( | ||
1995 | &isp->isp_res.subdev.entity, RESZ_PAD_SOURCE, | ||
1996 | &isp->isp_res.video_out.video.entity, 0, 0); | ||
1997 | |||
1998 | if (ret < 0) | ||
1999 | return ret; | ||
2000 | |||
2001 | /* Create links between entities. */ | ||
2002 | ret = media_create_pad_link( | ||
2003 | &isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE, | ||
2004 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0); | ||
2005 | if (ret < 0) | ||
2006 | return ret; | ||
2007 | |||
2008 | ret = media_create_pad_link( | ||
2009 | &isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE, | ||
2010 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0); | ||
2011 | if (ret < 0) | ||
2012 | return ret; | ||
2013 | |||
2014 | ret = media_create_pad_link( | ||
2015 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP, | ||
2016 | &isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0); | ||
2017 | if (ret < 0) | ||
2018 | return ret; | ||
2019 | |||
2020 | ret = media_create_pad_link( | ||
2021 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF, | ||
2022 | &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0); | ||
2023 | if (ret < 0) | ||
2024 | return ret; | ||
2025 | |||
2026 | ret = media_create_pad_link( | ||
2027 | &isp->isp_prev.subdev.entity, PREV_PAD_SOURCE, | ||
2028 | &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0); | ||
2029 | if (ret < 0) | ||
2030 | return ret; | ||
2031 | |||
2032 | ret = media_create_pad_link( | ||
2033 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP, | ||
2034 | &isp->isp_aewb.subdev.entity, 0, | ||
2035 | MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); | ||
2036 | if (ret < 0) | ||
2037 | return ret; | ||
2038 | |||
2039 | ret = media_create_pad_link( | ||
2040 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP, | ||
2041 | &isp->isp_af.subdev.entity, 0, | ||
2042 | MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); | ||
2043 | if (ret < 0) | ||
2044 | return ret; | ||
2045 | |||
2046 | ret = media_create_pad_link( | ||
2047 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP, | ||
2048 | &isp->isp_hist.subdev.entity, 0, | ||
2049 | MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); | ||
2050 | if (ret < 0) | ||
2051 | return ret; | ||
2052 | |||
2053 | return 0; | ||
2054 | } | ||
2055 | |||
1933 | static void isp_cleanup_modules(struct isp_device *isp) | 2056 | static void isp_cleanup_modules(struct isp_device *isp) |
1934 | { | 2057 | { |
1935 | omap3isp_h3a_aewb_cleanup(isp); | 2058 | omap3isp_h3a_aewb_cleanup(isp); |
@@ -2000,62 +2123,8 @@ static int isp_initialize_modules(struct isp_device *isp) | |||
2000 | goto error_h3a_af; | 2123 | goto error_h3a_af; |
2001 | } | 2124 | } |
2002 | 2125 | ||
2003 | /* Connect the submodules. */ | ||
2004 | ret = media_entity_create_link( | ||
2005 | &isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE, | ||
2006 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0); | ||
2007 | if (ret < 0) | ||
2008 | goto error_link; | ||
2009 | |||
2010 | ret = media_entity_create_link( | ||
2011 | &isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE, | ||
2012 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0); | ||
2013 | if (ret < 0) | ||
2014 | goto error_link; | ||
2015 | |||
2016 | ret = media_entity_create_link( | ||
2017 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP, | ||
2018 | &isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0); | ||
2019 | if (ret < 0) | ||
2020 | goto error_link; | ||
2021 | |||
2022 | ret = media_entity_create_link( | ||
2023 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF, | ||
2024 | &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0); | ||
2025 | if (ret < 0) | ||
2026 | goto error_link; | ||
2027 | |||
2028 | ret = media_entity_create_link( | ||
2029 | &isp->isp_prev.subdev.entity, PREV_PAD_SOURCE, | ||
2030 | &isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0); | ||
2031 | if (ret < 0) | ||
2032 | goto error_link; | ||
2033 | |||
2034 | ret = media_entity_create_link( | ||
2035 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP, | ||
2036 | &isp->isp_aewb.subdev.entity, 0, | ||
2037 | MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); | ||
2038 | if (ret < 0) | ||
2039 | goto error_link; | ||
2040 | |||
2041 | ret = media_entity_create_link( | ||
2042 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP, | ||
2043 | &isp->isp_af.subdev.entity, 0, | ||
2044 | MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); | ||
2045 | if (ret < 0) | ||
2046 | goto error_link; | ||
2047 | |||
2048 | ret = media_entity_create_link( | ||
2049 | &isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP, | ||
2050 | &isp->isp_hist.subdev.entity, 0, | ||
2051 | MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); | ||
2052 | if (ret < 0) | ||
2053 | goto error_link; | ||
2054 | |||
2055 | return 0; | 2126 | return 0; |
2056 | 2127 | ||
2057 | error_link: | ||
2058 | omap3isp_h3a_af_cleanup(isp); | ||
2059 | error_h3a_af: | 2128 | error_h3a_af: |
2060 | omap3isp_h3a_aewb_cleanup(isp); | 2129 | omap3isp_h3a_aewb_cleanup(isp); |
2061 | error_h3a_aewb: | 2130 | error_h3a_aewb: |
@@ -2149,6 +2218,8 @@ static int isp_remove(struct platform_device *pdev) | |||
2149 | isp_detach_iommu(isp); | 2218 | isp_detach_iommu(isp); |
2150 | __omap3isp_put(isp, false); | 2219 | __omap3isp_put(isp, false); |
2151 | 2220 | ||
2221 | media_entity_enum_cleanup(&isp->crashed); | ||
2222 | |||
2152 | return 0; | 2223 | return 0; |
2153 | } | 2224 | } |
2154 | 2225 | ||
@@ -2278,28 +2349,43 @@ static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async, | |||
2278 | struct v4l2_subdev *subdev, | 2349 | struct v4l2_subdev *subdev, |
2279 | struct v4l2_async_subdev *asd) | 2350 | struct v4l2_async_subdev *asd) |
2280 | { | 2351 | { |
2281 | struct isp_device *isp = container_of(async, struct isp_device, | ||
2282 | notifier); | ||
2283 | struct isp_async_subdev *isd = | 2352 | struct isp_async_subdev *isd = |
2284 | container_of(asd, struct isp_async_subdev, asd); | 2353 | container_of(asd, struct isp_async_subdev, asd); |
2285 | int ret; | ||
2286 | |||
2287 | ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface); | ||
2288 | if (ret < 0) | ||
2289 | return ret; | ||
2290 | 2354 | ||
2291 | isd->sd = subdev; | 2355 | isd->sd = subdev; |
2292 | isd->sd->host_priv = &isd->bus; | 2356 | isd->sd->host_priv = &isd->bus; |
2293 | 2357 | ||
2294 | return ret; | 2358 | return 0; |
2295 | } | 2359 | } |
2296 | 2360 | ||
2297 | static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) | 2361 | static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) |
2298 | { | 2362 | { |
2299 | struct isp_device *isp = container_of(async, struct isp_device, | 2363 | struct isp_device *isp = container_of(async, struct isp_device, |
2300 | notifier); | 2364 | notifier); |
2365 | struct v4l2_device *v4l2_dev = &isp->v4l2_dev; | ||
2366 | struct v4l2_subdev *sd; | ||
2367 | struct isp_bus_cfg *bus; | ||
2368 | int ret; | ||
2369 | |||
2370 | ret = media_entity_enum_init(&isp->crashed, &isp->media_dev); | ||
2371 | if (ret) | ||
2372 | return ret; | ||
2301 | 2373 | ||
2302 | return v4l2_device_register_subdev_nodes(&isp->v4l2_dev); | 2374 | list_for_each_entry(sd, &v4l2_dev->subdevs, list) { |
2375 | /* Only try to link entities whose interface was set on bound */ | ||
2376 | if (sd->host_priv) { | ||
2377 | bus = (struct isp_bus_cfg *)sd->host_priv; | ||
2378 | ret = isp_link_entity(isp, &sd->entity, bus->interface); | ||
2379 | if (ret < 0) | ||
2380 | return ret; | ||
2381 | } | ||
2382 | } | ||
2383 | |||
2384 | ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev); | ||
2385 | if (ret < 0) | ||
2386 | return ret; | ||
2387 | |||
2388 | return media_device_register(&isp->media_dev); | ||
2303 | } | 2389 | } |
2304 | 2390 | ||
2305 | /* | 2391 | /* |
@@ -2465,6 +2551,10 @@ static int isp_probe(struct platform_device *pdev) | |||
2465 | if (ret < 0) | 2551 | if (ret < 0) |
2466 | goto error_modules; | 2552 | goto error_modules; |
2467 | 2553 | ||
2554 | ret = isp_create_links(isp); | ||
2555 | if (ret < 0) | ||
2556 | goto error_register_entities; | ||
2557 | |||
2468 | isp->notifier.bound = isp_subdev_notifier_bound; | 2558 | isp->notifier.bound = isp_subdev_notifier_bound; |
2469 | isp->notifier.complete = isp_subdev_notifier_complete; | 2559 | isp->notifier.complete = isp_subdev_notifier_complete; |
2470 | 2560 | ||
diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index 5acc2e6511a5..49b7f71ac968 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #ifndef OMAP3_ISP_CORE_H | 17 | #ifndef OMAP3_ISP_CORE_H |
18 | #define OMAP3_ISP_CORE_H | 18 | #define OMAP3_ISP_CORE_H |
19 | 19 | ||
20 | #include <media/media-entity.h> | ||
20 | #include <media/v4l2-async.h> | 21 | #include <media/v4l2-async.h> |
21 | #include <media/v4l2-device.h> | 22 | #include <media/v4l2-device.h> |
22 | #include <linux/clk-provider.h> | 23 | #include <linux/clk-provider.h> |
@@ -152,7 +153,7 @@ struct isp_xclk { | |||
152 | * @stat_lock: Spinlock for handling statistics | 153 | * @stat_lock: Spinlock for handling statistics |
153 | * @isp_mutex: Mutex for serializing requests to ISP. | 154 | * @isp_mutex: Mutex for serializing requests to ISP. |
154 | * @stop_failure: Indicates that an entity failed to stop. | 155 | * @stop_failure: Indicates that an entity failed to stop. |
155 | * @crashed: Bitmask of crashed entities (indexed by entity ID) | 156 | * @crashed: Crashed ent_enum |
156 | * @has_context: Context has been saved at least once and can be restored. | 157 | * @has_context: Context has been saved at least once and can be restored. |
157 | * @ref_count: Reference count for handling multiple ISP requests. | 158 | * @ref_count: Reference count for handling multiple ISP requests. |
158 | * @cam_ick: Pointer to camera interface clock structure. | 159 | * @cam_ick: Pointer to camera interface clock structure. |
@@ -176,6 +177,7 @@ struct isp_device { | |||
176 | struct v4l2_device v4l2_dev; | 177 | struct v4l2_device v4l2_dev; |
177 | struct v4l2_async_notifier notifier; | 178 | struct v4l2_async_notifier notifier; |
178 | struct media_device media_dev; | 179 | struct media_device media_dev; |
180 | struct media_entity_graph pm_count_graph; | ||
179 | struct device *dev; | 181 | struct device *dev; |
180 | u32 revision; | 182 | u32 revision; |
181 | 183 | ||
@@ -194,7 +196,7 @@ struct isp_device { | |||
194 | spinlock_t stat_lock; /* common lock for statistic drivers */ | 196 | spinlock_t stat_lock; /* common lock for statistic drivers */ |
195 | struct mutex isp_mutex; /* For handling ref_count field */ | 197 | struct mutex isp_mutex; /* For handling ref_count field */ |
196 | bool stop_failure; | 198 | bool stop_failure; |
197 | u32 crashed; | 199 | struct media_entity_enum crashed; |
198 | int has_context; | 200 | int has_context; |
199 | int ref_count; | 201 | int ref_count; |
200 | unsigned int autoidle; | 202 | unsigned int autoidle; |
@@ -265,7 +267,8 @@ void omap3isp_subclk_enable(struct isp_device *isp, | |||
265 | void omap3isp_subclk_disable(struct isp_device *isp, | 267 | void omap3isp_subclk_disable(struct isp_device *isp, |
266 | enum isp_subclk_resource res); | 268 | enum isp_subclk_resource res); |
267 | 269 | ||
268 | int omap3isp_pipeline_pm_use(struct media_entity *entity, int use); | 270 | int omap3isp_pipeline_pm_use(struct media_entity *entity, int use, |
271 | struct media_entity_graph *graph); | ||
269 | 272 | ||
270 | int omap3isp_register_entities(struct platform_device *pdev, | 273 | int omap3isp_register_entities(struct platform_device *pdev, |
271 | struct v4l2_device *v4l2_dev); | 274 | struct v4l2_device *v4l2_dev); |
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index a6a61cce43dd..bb3974c98e37 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c | |||
@@ -1608,7 +1608,7 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc) | |||
1608 | /* Wait for the CCDC to become idle. */ | 1608 | /* Wait for the CCDC to become idle. */ |
1609 | if (ccdc_sbl_wait_idle(ccdc, 1000)) { | 1609 | if (ccdc_sbl_wait_idle(ccdc, 1000)) { |
1610 | dev_info(isp->dev, "CCDC won't become idle!\n"); | 1610 | dev_info(isp->dev, "CCDC won't become idle!\n"); |
1611 | isp->crashed |= 1U << ccdc->subdev.entity.id; | 1611 | media_entity_enum_set(&isp->crashed, &ccdc->subdev.entity); |
1612 | omap3isp_pipeline_cancel_stream(pipe); | 1612 | omap3isp_pipeline_cancel_stream(pipe); |
1613 | return 0; | 1613 | return 0; |
1614 | } | 1614 | } |
@@ -2513,9 +2513,14 @@ static int ccdc_link_setup(struct media_entity *entity, | |||
2513 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 2513 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
2514 | struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd); | 2514 | struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd); |
2515 | struct isp_device *isp = to_isp_device(ccdc); | 2515 | struct isp_device *isp = to_isp_device(ccdc); |
2516 | unsigned int index = local->index; | ||
2516 | 2517 | ||
2517 | switch (local->index | media_entity_type(remote->entity)) { | 2518 | /* FIXME: this is actually a hack! */ |
2518 | case CCDC_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 2519 | if (is_media_entity_v4l2_subdev(remote->entity)) |
2520 | index |= 2 << 16; | ||
2521 | |||
2522 | switch (index) { | ||
2523 | case CCDC_PAD_SINK | 2 << 16: | ||
2519 | /* Read from the sensor (parallel interface), CCP2, CSI2a or | 2524 | /* Read from the sensor (parallel interface), CCP2, CSI2a or |
2520 | * CSI2c. | 2525 | * CSI2c. |
2521 | */ | 2526 | */ |
@@ -2543,7 +2548,7 @@ static int ccdc_link_setup(struct media_entity *entity, | |||
2543 | * Revisit this when it will be implemented, and return -EBUSY for now. | 2548 | * Revisit this when it will be implemented, and return -EBUSY for now. |
2544 | */ | 2549 | */ |
2545 | 2550 | ||
2546 | case CCDC_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV: | 2551 | case CCDC_PAD_SOURCE_VP | 2 << 16: |
2547 | /* Write to preview engine, histogram and H3A. When none of | 2552 | /* Write to preview engine, histogram and H3A. When none of |
2548 | * those links are active, the video port can be disabled. | 2553 | * those links are active, the video port can be disabled. |
2549 | */ | 2554 | */ |
@@ -2556,7 +2561,7 @@ static int ccdc_link_setup(struct media_entity *entity, | |||
2556 | } | 2561 | } |
2557 | break; | 2562 | break; |
2558 | 2563 | ||
2559 | case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_DEVNODE: | 2564 | case CCDC_PAD_SOURCE_OF: |
2560 | /* Write to memory */ | 2565 | /* Write to memory */ |
2561 | if (flags & MEDIA_LNK_FL_ENABLED) { | 2566 | if (flags & MEDIA_LNK_FL_ENABLED) { |
2562 | if (ccdc->output & ~CCDC_OUTPUT_MEMORY) | 2567 | if (ccdc->output & ~CCDC_OUTPUT_MEMORY) |
@@ -2567,7 +2572,7 @@ static int ccdc_link_setup(struct media_entity *entity, | |||
2567 | } | 2572 | } |
2568 | break; | 2573 | break; |
2569 | 2574 | ||
2570 | case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_V4L2_SUBDEV: | 2575 | case CCDC_PAD_SOURCE_OF | 2 << 16: |
2571 | /* Write to resizer */ | 2576 | /* Write to resizer */ |
2572 | if (flags & MEDIA_LNK_FL_ENABLED) { | 2577 | if (flags & MEDIA_LNK_FL_ENABLED) { |
2573 | if (ccdc->output & ~CCDC_OUTPUT_RESIZER) | 2578 | if (ccdc->output & ~CCDC_OUTPUT_RESIZER) |
@@ -2650,7 +2655,7 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc) | |||
2650 | pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_SOURCE; | 2655 | pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_SOURCE; |
2651 | 2656 | ||
2652 | me->ops = &ccdc_media_ops; | 2657 | me->ops = &ccdc_media_ops; |
2653 | ret = media_entity_init(me, CCDC_PADS_NUM, pads, 0); | 2658 | ret = media_entity_pads_init(me, CCDC_PADS_NUM, pads); |
2654 | if (ret < 0) | 2659 | if (ret < 0) |
2655 | return ret; | 2660 | return ret; |
2656 | 2661 | ||
@@ -2664,19 +2669,11 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc) | |||
2664 | 2669 | ||
2665 | ret = omap3isp_video_init(&ccdc->video_out, "CCDC"); | 2670 | ret = omap3isp_video_init(&ccdc->video_out, "CCDC"); |
2666 | if (ret < 0) | 2671 | if (ret < 0) |
2667 | goto error_video; | 2672 | goto error; |
2668 | |||
2669 | /* Connect the CCDC subdev to the video node. */ | ||
2670 | ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF, | ||
2671 | &ccdc->video_out.video.entity, 0, 0); | ||
2672 | if (ret < 0) | ||
2673 | goto error_link; | ||
2674 | 2673 | ||
2675 | return 0; | 2674 | return 0; |
2676 | 2675 | ||
2677 | error_link: | 2676 | error: |
2678 | omap3isp_video_cleanup(&ccdc->video_out); | ||
2679 | error_video: | ||
2680 | media_entity_cleanup(me); | 2677 | media_entity_cleanup(me); |
2681 | return ret; | 2678 | return ret; |
2682 | } | 2679 | } |
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index 38e6a974c5b1..ca095238510d 100644 --- a/drivers/media/platform/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c | |||
@@ -956,9 +956,14 @@ static int ccp2_link_setup(struct media_entity *entity, | |||
956 | { | 956 | { |
957 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 957 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
958 | struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd); | 958 | struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd); |
959 | unsigned int index = local->index; | ||
959 | 960 | ||
960 | switch (local->index | media_entity_type(remote->entity)) { | 961 | /* FIXME: this is actually a hack! */ |
961 | case CCP2_PAD_SINK | MEDIA_ENT_T_DEVNODE: | 962 | if (is_media_entity_v4l2_subdev(remote->entity)) |
963 | index |= 2 << 16; | ||
964 | |||
965 | switch (index) { | ||
966 | case CCP2_PAD_SINK: | ||
962 | /* read from memory */ | 967 | /* read from memory */ |
963 | if (flags & MEDIA_LNK_FL_ENABLED) { | 968 | if (flags & MEDIA_LNK_FL_ENABLED) { |
964 | if (ccp2->input == CCP2_INPUT_SENSOR) | 969 | if (ccp2->input == CCP2_INPUT_SENSOR) |
@@ -970,7 +975,7 @@ static int ccp2_link_setup(struct media_entity *entity, | |||
970 | } | 975 | } |
971 | break; | 976 | break; |
972 | 977 | ||
973 | case CCP2_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 978 | case CCP2_PAD_SINK | 2 << 16: |
974 | /* read from sensor/phy */ | 979 | /* read from sensor/phy */ |
975 | if (flags & MEDIA_LNK_FL_ENABLED) { | 980 | if (flags & MEDIA_LNK_FL_ENABLED) { |
976 | if (ccp2->input == CCP2_INPUT_MEMORY) | 981 | if (ccp2->input == CCP2_INPUT_MEMORY) |
@@ -981,7 +986,7 @@ static int ccp2_link_setup(struct media_entity *entity, | |||
981 | ccp2->input = CCP2_INPUT_NONE; | 986 | ccp2->input = CCP2_INPUT_NONE; |
982 | } break; | 987 | } break; |
983 | 988 | ||
984 | case CCP2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: | 989 | case CCP2_PAD_SOURCE | 2 << 16: |
985 | /* write to video port/ccdc */ | 990 | /* write to video port/ccdc */ |
986 | if (flags & MEDIA_LNK_FL_ENABLED) | 991 | if (flags & MEDIA_LNK_FL_ENABLED) |
987 | ccp2->output = CCP2_OUTPUT_CCDC; | 992 | ccp2->output = CCP2_OUTPUT_CCDC; |
@@ -1071,7 +1076,7 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2) | |||
1071 | pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; | 1076 | pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; |
1072 | 1077 | ||
1073 | me->ops = &ccp2_media_ops; | 1078 | me->ops = &ccp2_media_ops; |
1074 | ret = media_entity_init(me, CCP2_PADS_NUM, pads, 0); | 1079 | ret = media_entity_pads_init(me, CCP2_PADS_NUM, pads); |
1075 | if (ret < 0) | 1080 | if (ret < 0) |
1076 | return ret; | 1081 | return ret; |
1077 | 1082 | ||
@@ -1097,19 +1102,11 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2) | |||
1097 | 1102 | ||
1098 | ret = omap3isp_video_init(&ccp2->video_in, "CCP2"); | 1103 | ret = omap3isp_video_init(&ccp2->video_in, "CCP2"); |
1099 | if (ret < 0) | 1104 | if (ret < 0) |
1100 | goto error_video; | 1105 | goto error; |
1101 | |||
1102 | /* Connect the video node to the ccp2 subdev. */ | ||
1103 | ret = media_entity_create_link(&ccp2->video_in.video.entity, 0, | ||
1104 | &ccp2->subdev.entity, CCP2_PAD_SINK, 0); | ||
1105 | if (ret < 0) | ||
1106 | goto error_link; | ||
1107 | 1106 | ||
1108 | return 0; | 1107 | return 0; |
1109 | 1108 | ||
1110 | error_link: | 1109 | error: |
1111 | omap3isp_video_cleanup(&ccp2->video_in); | ||
1112 | error_video: | ||
1113 | media_entity_cleanup(&ccp2->subdev.entity); | 1110 | media_entity_cleanup(&ccp2->subdev.entity); |
1114 | return ret; | 1111 | return ret; |
1115 | } | 1112 | } |
diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c index a78338d012b4..f75a1be29d84 100644 --- a/drivers/media/platform/omap3isp/ispcsi2.c +++ b/drivers/media/platform/omap3isp/ispcsi2.c | |||
@@ -1144,14 +1144,19 @@ static int csi2_link_setup(struct media_entity *entity, | |||
1144 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 1144 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
1145 | struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd); | 1145 | struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd); |
1146 | struct isp_csi2_ctrl_cfg *ctrl = &csi2->ctrl; | 1146 | struct isp_csi2_ctrl_cfg *ctrl = &csi2->ctrl; |
1147 | unsigned int index = local->index; | ||
1147 | 1148 | ||
1148 | /* | 1149 | /* |
1149 | * The ISP core doesn't support pipelines with multiple video outputs. | 1150 | * The ISP core doesn't support pipelines with multiple video outputs. |
1150 | * Revisit this when it will be implemented, and return -EBUSY for now. | 1151 | * Revisit this when it will be implemented, and return -EBUSY for now. |
1151 | */ | 1152 | */ |
1152 | 1153 | ||
1153 | switch (local->index | media_entity_type(remote->entity)) { | 1154 | /* FIXME: this is actually a hack! */ |
1154 | case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: | 1155 | if (is_media_entity_v4l2_subdev(remote->entity)) |
1156 | index |= 2 << 16; | ||
1157 | |||
1158 | switch (index) { | ||
1159 | case CSI2_PAD_SOURCE: | ||
1155 | if (flags & MEDIA_LNK_FL_ENABLED) { | 1160 | if (flags & MEDIA_LNK_FL_ENABLED) { |
1156 | if (csi2->output & ~CSI2_OUTPUT_MEMORY) | 1161 | if (csi2->output & ~CSI2_OUTPUT_MEMORY) |
1157 | return -EBUSY; | 1162 | return -EBUSY; |
@@ -1161,7 +1166,7 @@ static int csi2_link_setup(struct media_entity *entity, | |||
1161 | } | 1166 | } |
1162 | break; | 1167 | break; |
1163 | 1168 | ||
1164 | case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: | 1169 | case CSI2_PAD_SOURCE | 2 << 16: |
1165 | if (flags & MEDIA_LNK_FL_ENABLED) { | 1170 | if (flags & MEDIA_LNK_FL_ENABLED) { |
1166 | if (csi2->output & ~CSI2_OUTPUT_CCDC) | 1171 | if (csi2->output & ~CSI2_OUTPUT_CCDC) |
1167 | return -EBUSY; | 1172 | return -EBUSY; |
@@ -1245,7 +1250,7 @@ static int csi2_init_entities(struct isp_csi2_device *csi2) | |||
1245 | | MEDIA_PAD_FL_MUST_CONNECT; | 1250 | | MEDIA_PAD_FL_MUST_CONNECT; |
1246 | 1251 | ||
1247 | me->ops = &csi2_media_ops; | 1252 | me->ops = &csi2_media_ops; |
1248 | ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0); | 1253 | ret = media_entity_pads_init(me, CSI2_PADS_NUM, pads); |
1249 | if (ret < 0) | 1254 | if (ret < 0) |
1250 | return ret; | 1255 | return ret; |
1251 | 1256 | ||
@@ -1264,16 +1269,8 @@ static int csi2_init_entities(struct isp_csi2_device *csi2) | |||
1264 | if (ret < 0) | 1269 | if (ret < 0) |
1265 | goto error_video; | 1270 | goto error_video; |
1266 | 1271 | ||
1267 | /* Connect the CSI2 subdev to the video node. */ | ||
1268 | ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE, | ||
1269 | &csi2->video_out.video.entity, 0, 0); | ||
1270 | if (ret < 0) | ||
1271 | goto error_link; | ||
1272 | |||
1273 | return 0; | 1272 | return 0; |
1274 | 1273 | ||
1275 | error_link: | ||
1276 | omap3isp_video_cleanup(&csi2->video_out); | ||
1277 | error_video: | 1274 | error_video: |
1278 | media_entity_cleanup(&csi2->subdev.entity); | 1275 | media_entity_cleanup(&csi2->subdev.entity); |
1279 | return ret; | 1276 | return ret; |
diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index 13803270d104..84a96670e2e7 100644 --- a/drivers/media/platform/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c | |||
@@ -2144,9 +2144,14 @@ static int preview_link_setup(struct media_entity *entity, | |||
2144 | { | 2144 | { |
2145 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 2145 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
2146 | struct isp_prev_device *prev = v4l2_get_subdevdata(sd); | 2146 | struct isp_prev_device *prev = v4l2_get_subdevdata(sd); |
2147 | unsigned int index = local->index; | ||
2147 | 2148 | ||
2148 | switch (local->index | media_entity_type(remote->entity)) { | 2149 | /* FIXME: this is actually a hack! */ |
2149 | case PREV_PAD_SINK | MEDIA_ENT_T_DEVNODE: | 2150 | if (is_media_entity_v4l2_subdev(remote->entity)) |
2151 | index |= 2 << 16; | ||
2152 | |||
2153 | switch (index) { | ||
2154 | case PREV_PAD_SINK: | ||
2150 | /* read from memory */ | 2155 | /* read from memory */ |
2151 | if (flags & MEDIA_LNK_FL_ENABLED) { | 2156 | if (flags & MEDIA_LNK_FL_ENABLED) { |
2152 | if (prev->input == PREVIEW_INPUT_CCDC) | 2157 | if (prev->input == PREVIEW_INPUT_CCDC) |
@@ -2158,7 +2163,7 @@ static int preview_link_setup(struct media_entity *entity, | |||
2158 | } | 2163 | } |
2159 | break; | 2164 | break; |
2160 | 2165 | ||
2161 | case PREV_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 2166 | case PREV_PAD_SINK | 2 << 16: |
2162 | /* read from ccdc */ | 2167 | /* read from ccdc */ |
2163 | if (flags & MEDIA_LNK_FL_ENABLED) { | 2168 | if (flags & MEDIA_LNK_FL_ENABLED) { |
2164 | if (prev->input == PREVIEW_INPUT_MEMORY) | 2169 | if (prev->input == PREVIEW_INPUT_MEMORY) |
@@ -2175,7 +2180,7 @@ static int preview_link_setup(struct media_entity *entity, | |||
2175 | * Revisit this when it will be implemented, and return -EBUSY for now. | 2180 | * Revisit this when it will be implemented, and return -EBUSY for now. |
2176 | */ | 2181 | */ |
2177 | 2182 | ||
2178 | case PREV_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: | 2183 | case PREV_PAD_SOURCE: |
2179 | /* write to memory */ | 2184 | /* write to memory */ |
2180 | if (flags & MEDIA_LNK_FL_ENABLED) { | 2185 | if (flags & MEDIA_LNK_FL_ENABLED) { |
2181 | if (prev->output & ~PREVIEW_OUTPUT_MEMORY) | 2186 | if (prev->output & ~PREVIEW_OUTPUT_MEMORY) |
@@ -2186,7 +2191,7 @@ static int preview_link_setup(struct media_entity *entity, | |||
2186 | } | 2191 | } |
2187 | break; | 2192 | break; |
2188 | 2193 | ||
2189 | case PREV_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: | 2194 | case PREV_PAD_SOURCE | 2 << 16: |
2190 | /* write to resizer */ | 2195 | /* write to resizer */ |
2191 | if (flags & MEDIA_LNK_FL_ENABLED) { | 2196 | if (flags & MEDIA_LNK_FL_ENABLED) { |
2192 | if (prev->output & ~PREVIEW_OUTPUT_RESIZER) | 2197 | if (prev->output & ~PREVIEW_OUTPUT_RESIZER) |
@@ -2282,7 +2287,7 @@ static int preview_init_entities(struct isp_prev_device *prev) | |||
2282 | pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; | 2287 | pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; |
2283 | 2288 | ||
2284 | me->ops = &preview_media_ops; | 2289 | me->ops = &preview_media_ops; |
2285 | ret = media_entity_init(me, PREV_PADS_NUM, pads, 0); | 2290 | ret = media_entity_pads_init(me, PREV_PADS_NUM, pads); |
2286 | if (ret < 0) | 2291 | if (ret < 0) |
2287 | return ret; | 2292 | return ret; |
2288 | 2293 | ||
@@ -2311,21 +2316,8 @@ static int preview_init_entities(struct isp_prev_device *prev) | |||
2311 | if (ret < 0) | 2316 | if (ret < 0) |
2312 | goto error_video_out; | 2317 | goto error_video_out; |
2313 | 2318 | ||
2314 | /* Connect the video nodes to the previewer subdev. */ | ||
2315 | ret = media_entity_create_link(&prev->video_in.video.entity, 0, | ||
2316 | &prev->subdev.entity, PREV_PAD_SINK, 0); | ||
2317 | if (ret < 0) | ||
2318 | goto error_link; | ||
2319 | |||
2320 | ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE, | ||
2321 | &prev->video_out.video.entity, 0, 0); | ||
2322 | if (ret < 0) | ||
2323 | goto error_link; | ||
2324 | |||
2325 | return 0; | 2319 | return 0; |
2326 | 2320 | ||
2327 | error_link: | ||
2328 | omap3isp_video_cleanup(&prev->video_out); | ||
2329 | error_video_out: | 2321 | error_video_out: |
2330 | omap3isp_video_cleanup(&prev->video_in); | 2322 | omap3isp_video_cleanup(&prev->video_in); |
2331 | error_video_in: | 2323 | error_video_in: |
diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c index 7cfb43dc0ffd..0b6a87508584 100644 --- a/drivers/media/platform/omap3isp/ispresizer.c +++ b/drivers/media/platform/omap3isp/ispresizer.c | |||
@@ -1623,9 +1623,14 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1623 | { | 1623 | { |
1624 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 1624 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
1625 | struct isp_res_device *res = v4l2_get_subdevdata(sd); | 1625 | struct isp_res_device *res = v4l2_get_subdevdata(sd); |
1626 | unsigned int index = local->index; | ||
1626 | 1627 | ||
1627 | switch (local->index | media_entity_type(remote->entity)) { | 1628 | /* FIXME: this is actually a hack! */ |
1628 | case RESZ_PAD_SINK | MEDIA_ENT_T_DEVNODE: | 1629 | if (is_media_entity_v4l2_subdev(remote->entity)) |
1630 | index |= 2 << 16; | ||
1631 | |||
1632 | switch (index) { | ||
1633 | case RESZ_PAD_SINK: | ||
1629 | /* read from memory */ | 1634 | /* read from memory */ |
1630 | if (flags & MEDIA_LNK_FL_ENABLED) { | 1635 | if (flags & MEDIA_LNK_FL_ENABLED) { |
1631 | if (res->input == RESIZER_INPUT_VP) | 1636 | if (res->input == RESIZER_INPUT_VP) |
@@ -1637,7 +1642,7 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1637 | } | 1642 | } |
1638 | break; | 1643 | break; |
1639 | 1644 | ||
1640 | case RESZ_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 1645 | case RESZ_PAD_SINK | 2 << 16: |
1641 | /* read from ccdc or previewer */ | 1646 | /* read from ccdc or previewer */ |
1642 | if (flags & MEDIA_LNK_FL_ENABLED) { | 1647 | if (flags & MEDIA_LNK_FL_ENABLED) { |
1643 | if (res->input == RESIZER_INPUT_MEMORY) | 1648 | if (res->input == RESIZER_INPUT_MEMORY) |
@@ -1649,7 +1654,7 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1649 | } | 1654 | } |
1650 | break; | 1655 | break; |
1651 | 1656 | ||
1652 | case RESZ_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: | 1657 | case RESZ_PAD_SOURCE: |
1653 | /* resizer always write to memory */ | 1658 | /* resizer always write to memory */ |
1654 | break; | 1659 | break; |
1655 | 1660 | ||
@@ -1728,7 +1733,7 @@ static int resizer_init_entities(struct isp_res_device *res) | |||
1728 | pads[RESZ_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; | 1733 | pads[RESZ_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; |
1729 | 1734 | ||
1730 | me->ops = &resizer_media_ops; | 1735 | me->ops = &resizer_media_ops; |
1731 | ret = media_entity_init(me, RESZ_PADS_NUM, pads, 0); | 1736 | ret = media_entity_pads_init(me, RESZ_PADS_NUM, pads); |
1732 | if (ret < 0) | 1737 | if (ret < 0) |
1733 | return ret; | 1738 | return ret; |
1734 | 1739 | ||
@@ -1755,21 +1760,8 @@ static int resizer_init_entities(struct isp_res_device *res) | |||
1755 | 1760 | ||
1756 | res->video_out.video.entity.flags |= MEDIA_ENT_FL_DEFAULT; | 1761 | res->video_out.video.entity.flags |= MEDIA_ENT_FL_DEFAULT; |
1757 | 1762 | ||
1758 | /* Connect the video nodes to the resizer subdev. */ | ||
1759 | ret = media_entity_create_link(&res->video_in.video.entity, 0, | ||
1760 | &res->subdev.entity, RESZ_PAD_SINK, 0); | ||
1761 | if (ret < 0) | ||
1762 | goto error_link; | ||
1763 | |||
1764 | ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE, | ||
1765 | &res->video_out.video.entity, 0, 0); | ||
1766 | if (ret < 0) | ||
1767 | goto error_link; | ||
1768 | |||
1769 | return 0; | 1763 | return 0; |
1770 | 1764 | ||
1771 | error_link: | ||
1772 | omap3isp_video_cleanup(&res->video_out); | ||
1773 | error_video_out: | 1765 | error_video_out: |
1774 | omap3isp_video_cleanup(&res->video_in); | 1766 | omap3isp_video_cleanup(&res->video_in); |
1775 | error_video_in: | 1767 | error_video_in: |
diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c index 94d4c295d3d0..1b9217d3b1b6 100644 --- a/drivers/media/platform/omap3isp/ispstat.c +++ b/drivers/media/platform/omap3isp/ispstat.c | |||
@@ -1028,7 +1028,7 @@ static int isp_stat_init_entities(struct ispstat *stat, const char *name, | |||
1028 | stat->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; | 1028 | stat->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; |
1029 | me->ops = NULL; | 1029 | me->ops = NULL; |
1030 | 1030 | ||
1031 | return media_entity_init(me, 1, &stat->pad, 0); | 1031 | return media_entity_pads_init(me, 1, &stat->pad); |
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | int omap3isp_stat_init(struct ispstat *stat, const char *name, | 1034 | int omap3isp_stat_init(struct ispstat *stat, const char *name, |
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index ecadca3e945b..994dfc0813f6 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c | |||
@@ -210,8 +210,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad) | |||
210 | 210 | ||
211 | remote = media_entity_remote_pad(&video->pad); | 211 | remote = media_entity_remote_pad(&video->pad); |
212 | 212 | ||
213 | if (remote == NULL || | 213 | if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) |
214 | media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
215 | return NULL; | 214 | return NULL; |
216 | 215 | ||
217 | if (pad) | 216 | if (pad) |
@@ -226,16 +225,23 @@ static int isp_video_get_graph_data(struct isp_video *video, | |||
226 | { | 225 | { |
227 | struct media_entity_graph graph; | 226 | struct media_entity_graph graph; |
228 | struct media_entity *entity = &video->video.entity; | 227 | struct media_entity *entity = &video->video.entity; |
229 | struct media_device *mdev = entity->parent; | 228 | struct media_device *mdev = entity->graph_obj.mdev; |
230 | struct isp_video *far_end = NULL; | 229 | struct isp_video *far_end = NULL; |
230 | int ret; | ||
231 | 231 | ||
232 | mutex_lock(&mdev->graph_mutex); | 232 | mutex_lock(&mdev->graph_mutex); |
233 | ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev); | ||
234 | if (ret) { | ||
235 | mutex_unlock(&mdev->graph_mutex); | ||
236 | return ret; | ||
237 | } | ||
238 | |||
233 | media_entity_graph_walk_start(&graph, entity); | 239 | media_entity_graph_walk_start(&graph, entity); |
234 | 240 | ||
235 | while ((entity = media_entity_graph_walk_next(&graph))) { | 241 | while ((entity = media_entity_graph_walk_next(&graph))) { |
236 | struct isp_video *__video; | 242 | struct isp_video *__video; |
237 | 243 | ||
238 | pipe->entities |= 1 << entity->id; | 244 | media_entity_enum_set(&pipe->ent_enum, entity); |
239 | 245 | ||
240 | if (far_end != NULL) | 246 | if (far_end != NULL) |
241 | continue; | 247 | continue; |
@@ -243,7 +249,7 @@ static int isp_video_get_graph_data(struct isp_video *video, | |||
243 | if (entity == &video->video.entity) | 249 | if (entity == &video->video.entity) |
244 | continue; | 250 | continue; |
245 | 251 | ||
246 | if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) | 252 | if (!is_media_entity_v4l2_io(entity)) |
247 | continue; | 253 | continue; |
248 | 254 | ||
249 | __video = to_isp_video(media_entity_to_video_device(entity)); | 255 | __video = to_isp_video(media_entity_to_video_device(entity)); |
@@ -253,6 +259,8 @@ static int isp_video_get_graph_data(struct isp_video *video, | |||
253 | 259 | ||
254 | mutex_unlock(&mdev->graph_mutex); | 260 | mutex_unlock(&mdev->graph_mutex); |
255 | 261 | ||
262 | media_entity_graph_walk_cleanup(&graph); | ||
263 | |||
256 | if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 264 | if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
257 | pipe->input = far_end; | 265 | pipe->input = far_end; |
258 | pipe->output = video; | 266 | pipe->output = video; |
@@ -900,7 +908,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video, | |||
900 | 908 | ||
901 | for (i = 0; i < ARRAY_SIZE(ents); i++) { | 909 | for (i = 0; i < ARRAY_SIZE(ents); i++) { |
902 | /* Is the entity part of the pipeline? */ | 910 | /* Is the entity part of the pipeline? */ |
903 | if (!(pipe->entities & (1 << ents[i]->id))) | 911 | if (!media_entity_enum_test(&pipe->ent_enum, ents[i])) |
904 | continue; | 912 | continue; |
905 | 913 | ||
906 | /* ISP entities have always sink pad == 0. Find source. */ | 914 | /* ISP entities have always sink pad == 0. Find source. */ |
@@ -918,7 +926,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video, | |||
918 | return -EINVAL; | 926 | return -EINVAL; |
919 | } | 927 | } |
920 | 928 | ||
921 | if (media_entity_type(source) != MEDIA_ENT_T_V4L2_SUBDEV) | 929 | if (!is_media_entity_v4l2_subdev(source)) |
922 | return 0; | 930 | return 0; |
923 | 931 | ||
924 | pipe->external = media_entity_to_v4l2_subdev(source); | 932 | pipe->external = media_entity_to_v4l2_subdev(source); |
@@ -952,7 +960,8 @@ static int isp_video_check_external_subdevs(struct isp_video *video, | |||
952 | 960 | ||
953 | pipe->external_rate = ctrl.value64; | 961 | pipe->external_rate = ctrl.value64; |
954 | 962 | ||
955 | if (pipe->entities & (1 << isp->isp_ccdc.subdev.entity.id)) { | 963 | if (media_entity_enum_test(&pipe->ent_enum, |
964 | &isp->isp_ccdc.subdev.entity)) { | ||
956 | unsigned int rate = UINT_MAX; | 965 | unsigned int rate = UINT_MAX; |
957 | /* | 966 | /* |
958 | * Check that maximum allowed CCDC pixel rate isn't | 967 | * Check that maximum allowed CCDC pixel rate isn't |
@@ -1018,7 +1027,9 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) | |||
1018 | pipe = video->video.entity.pipe | 1027 | pipe = video->video.entity.pipe |
1019 | ? to_isp_pipeline(&video->video.entity) : &video->pipe; | 1028 | ? to_isp_pipeline(&video->video.entity) : &video->pipe; |
1020 | 1029 | ||
1021 | pipe->entities = 0; | 1030 | ret = media_entity_enum_init(&pipe->ent_enum, &video->isp->media_dev); |
1031 | if (ret) | ||
1032 | goto err_enum_init; | ||
1022 | 1033 | ||
1023 | /* TODO: Implement PM QoS */ | 1034 | /* TODO: Implement PM QoS */ |
1024 | pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]); | 1035 | pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]); |
@@ -1092,6 +1103,7 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) | |||
1092 | } | 1103 | } |
1093 | 1104 | ||
1094 | mutex_unlock(&video->stream_lock); | 1105 | mutex_unlock(&video->stream_lock); |
1106 | |||
1095 | return 0; | 1107 | return 0; |
1096 | 1108 | ||
1097 | err_set_stream: | 1109 | err_set_stream: |
@@ -1112,7 +1124,11 @@ err_pipeline_start: | |||
1112 | INIT_LIST_HEAD(&video->dmaqueue); | 1124 | INIT_LIST_HEAD(&video->dmaqueue); |
1113 | video->queue = NULL; | 1125 | video->queue = NULL; |
1114 | 1126 | ||
1127 | media_entity_enum_cleanup(&pipe->ent_enum); | ||
1128 | |||
1129 | err_enum_init: | ||
1115 | mutex_unlock(&video->stream_lock); | 1130 | mutex_unlock(&video->stream_lock); |
1131 | |||
1116 | return ret; | 1132 | return ret; |
1117 | } | 1133 | } |
1118 | 1134 | ||
@@ -1164,6 +1180,8 @@ isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) | |||
1164 | /* TODO: Implement PM QoS */ | 1180 | /* TODO: Implement PM QoS */ |
1165 | media_entity_pipeline_stop(&video->video.entity); | 1181 | media_entity_pipeline_stop(&video->video.entity); |
1166 | 1182 | ||
1183 | media_entity_enum_cleanup(&pipe->ent_enum); | ||
1184 | |||
1167 | done: | 1185 | done: |
1168 | mutex_unlock(&video->stream_lock); | 1186 | mutex_unlock(&video->stream_lock); |
1169 | return 0; | 1187 | return 0; |
@@ -1243,7 +1261,12 @@ static int isp_video_open(struct file *file) | |||
1243 | goto done; | 1261 | goto done; |
1244 | } | 1262 | } |
1245 | 1263 | ||
1246 | ret = omap3isp_pipeline_pm_use(&video->video.entity, 1); | 1264 | ret = media_entity_graph_walk_init(&handle->graph, |
1265 | &video->isp->media_dev); | ||
1266 | if (ret) | ||
1267 | goto done; | ||
1268 | |||
1269 | ret = omap3isp_pipeline_pm_use(&video->video.entity, 1, &handle->graph); | ||
1247 | if (ret < 0) { | 1270 | if (ret < 0) { |
1248 | omap3isp_put(video->isp); | 1271 | omap3isp_put(video->isp); |
1249 | goto done; | 1272 | goto done; |
@@ -1274,6 +1297,7 @@ static int isp_video_open(struct file *file) | |||
1274 | done: | 1297 | done: |
1275 | if (ret < 0) { | 1298 | if (ret < 0) { |
1276 | v4l2_fh_del(&handle->vfh); | 1299 | v4l2_fh_del(&handle->vfh); |
1300 | media_entity_graph_walk_cleanup(&handle->graph); | ||
1277 | kfree(handle); | 1301 | kfree(handle); |
1278 | } | 1302 | } |
1279 | 1303 | ||
@@ -1293,7 +1317,8 @@ static int isp_video_release(struct file *file) | |||
1293 | vb2_queue_release(&handle->queue); | 1317 | vb2_queue_release(&handle->queue); |
1294 | mutex_unlock(&video->queue_lock); | 1318 | mutex_unlock(&video->queue_lock); |
1295 | 1319 | ||
1296 | omap3isp_pipeline_pm_use(&video->video.entity, 0); | 1320 | omap3isp_pipeline_pm_use(&video->video.entity, 0, &handle->graph); |
1321 | media_entity_graph_walk_cleanup(&handle->graph); | ||
1297 | 1322 | ||
1298 | /* Release the file handle. */ | 1323 | /* Release the file handle. */ |
1299 | v4l2_fh_del(vfh); | 1324 | v4l2_fh_del(vfh); |
@@ -1367,7 +1392,7 @@ int omap3isp_video_init(struct isp_video *video, const char *name) | |||
1367 | if (IS_ERR(video->alloc_ctx)) | 1392 | if (IS_ERR(video->alloc_ctx)) |
1368 | return PTR_ERR(video->alloc_ctx); | 1393 | return PTR_ERR(video->alloc_ctx); |
1369 | 1394 | ||
1370 | ret = media_entity_init(&video->video.entity, 1, &video->pad, 0); | 1395 | ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); |
1371 | if (ret < 0) { | 1396 | if (ret < 0) { |
1372 | vb2_dma_contig_cleanup_ctx(video->alloc_ctx); | 1397 | vb2_dma_contig_cleanup_ctx(video->alloc_ctx); |
1373 | return ret; | 1398 | return ret; |
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h index bcf0e0acc8f3..156429878d64 100644 --- a/drivers/media/platform/omap3isp/ispvideo.h +++ b/drivers/media/platform/omap3isp/ispvideo.h | |||
@@ -80,7 +80,7 @@ enum isp_pipeline_state { | |||
80 | * struct isp_pipeline - An ISP hardware pipeline | 80 | * struct isp_pipeline - An ISP hardware pipeline |
81 | * @field: The field being processed by the pipeline | 81 | * @field: The field being processed by the pipeline |
82 | * @error: A hardware error occurred during capture | 82 | * @error: A hardware error occurred during capture |
83 | * @entities: Bitmask of entities in the pipeline (indexed by entity ID) | 83 | * @ent_enum: Entities in the pipeline |
84 | */ | 84 | */ |
85 | struct isp_pipeline { | 85 | struct isp_pipeline { |
86 | struct media_pipeline pipe; | 86 | struct media_pipeline pipe; |
@@ -89,7 +89,7 @@ struct isp_pipeline { | |||
89 | enum isp_pipeline_stream_state stream_state; | 89 | enum isp_pipeline_stream_state stream_state; |
90 | struct isp_video *input; | 90 | struct isp_video *input; |
91 | struct isp_video *output; | 91 | struct isp_video *output; |
92 | u32 entities; | 92 | struct media_entity_enum ent_enum; |
93 | unsigned long l3_ick; | 93 | unsigned long l3_ick; |
94 | unsigned int max_rate; | 94 | unsigned int max_rate; |
95 | enum v4l2_field field; | 95 | enum v4l2_field field; |
@@ -189,6 +189,7 @@ struct isp_video_fh { | |||
189 | struct vb2_queue queue; | 189 | struct vb2_queue queue; |
190 | struct v4l2_format format; | 190 | struct v4l2_format format; |
191 | struct v4l2_fract timeperframe; | 191 | struct v4l2_fract timeperframe; |
192 | struct media_entity_graph graph; | ||
192 | }; | 193 | }; |
193 | 194 | ||
194 | #define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh) | 195 | #define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh) |
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index ec3abbed87d9..bd060ef5d1e1 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c | |||
@@ -822,7 +822,7 @@ static int camif_pipeline_validate(struct camif_dev *camif) | |||
822 | 822 | ||
823 | /* Retrieve format at the sensor subdev source pad */ | 823 | /* Retrieve format at the sensor subdev source pad */ |
824 | pad = media_entity_remote_pad(&camif->pads[0]); | 824 | pad = media_entity_remote_pad(&camif->pads[0]); |
825 | if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | 825 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
826 | return -EPIPE; | 826 | return -EPIPE; |
827 | 827 | ||
828 | src_fmt.pad = pad->index; | 828 | src_fmt.pad = pad->index; |
@@ -1144,7 +1144,7 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx) | |||
1144 | goto err_vd_rel; | 1144 | goto err_vd_rel; |
1145 | 1145 | ||
1146 | vp->pad.flags = MEDIA_PAD_FL_SINK; | 1146 | vp->pad.flags = MEDIA_PAD_FL_SINK; |
1147 | ret = media_entity_init(&vfd->entity, 1, &vp->pad, 0); | 1147 | ret = media_entity_pads_init(&vfd->entity, 1, &vp->pad); |
1148 | if (ret) | 1148 | if (ret) |
1149 | goto err_vd_rel; | 1149 | goto err_vd_rel; |
1150 | 1150 | ||
@@ -1559,8 +1559,8 @@ int s3c_camif_create_subdev(struct camif_dev *camif) | |||
1559 | camif->pads[CAMIF_SD_PAD_SOURCE_C].flags = MEDIA_PAD_FL_SOURCE; | 1559 | camif->pads[CAMIF_SD_PAD_SOURCE_C].flags = MEDIA_PAD_FL_SOURCE; |
1560 | camif->pads[CAMIF_SD_PAD_SOURCE_P].flags = MEDIA_PAD_FL_SOURCE; | 1560 | camif->pads[CAMIF_SD_PAD_SOURCE_P].flags = MEDIA_PAD_FL_SOURCE; |
1561 | 1561 | ||
1562 | ret = media_entity_init(&sd->entity, CAMIF_SD_PADS_NUM, | 1562 | ret = media_entity_pads_init(&sd->entity, CAMIF_SD_PADS_NUM, |
1563 | camif->pads, 0); | 1563 | camif->pads); |
1564 | if (ret) | 1564 | if (ret) |
1565 | return ret; | 1565 | return ret; |
1566 | 1566 | ||
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index 1ba9bb08f5da..0b44b9accf50 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c | |||
@@ -263,7 +263,7 @@ static int camif_create_media_links(struct camif_dev *camif) | |||
263 | { | 263 | { |
264 | int i, ret; | 264 | int i, ret; |
265 | 265 | ||
266 | ret = media_entity_create_link(&camif->sensor.sd->entity, 0, | 266 | ret = media_create_pad_link(&camif->sensor.sd->entity, 0, |
267 | &camif->subdev.entity, CAMIF_SD_PAD_SINK, | 267 | &camif->subdev.entity, CAMIF_SD_PAD_SINK, |
268 | MEDIA_LNK_FL_IMMUTABLE | | 268 | MEDIA_LNK_FL_IMMUTABLE | |
269 | MEDIA_LNK_FL_ENABLED); | 269 | MEDIA_LNK_FL_ENABLED); |
@@ -271,7 +271,7 @@ static int camif_create_media_links(struct camif_dev *camif) | |||
271 | return ret; | 271 | return ret; |
272 | 272 | ||
273 | for (i = 1; i < CAMIF_SD_PADS_NUM && !ret; i++) { | 273 | for (i = 1; i < CAMIF_SD_PADS_NUM && !ret; i++) { |
274 | ret = media_entity_create_link(&camif->subdev.entity, i, | 274 | ret = media_create_pad_link(&camif->subdev.entity, i, |
275 | &camif->vp[i - 1].vdev.entity, 0, | 275 | &camif->vp[i - 1].vdev.entity, 0, |
276 | MEDIA_LNK_FL_IMMUTABLE | | 276 | MEDIA_LNK_FL_IMMUTABLE | |
277 | MEDIA_LNK_FL_ENABLED); | 277 | MEDIA_LNK_FL_ENABLED); |
@@ -305,7 +305,7 @@ static void camif_unregister_media_entities(struct camif_dev *camif) | |||
305 | /* | 305 | /* |
306 | * Media device | 306 | * Media device |
307 | */ | 307 | */ |
308 | static int camif_media_dev_register(struct camif_dev *camif) | 308 | static int camif_media_dev_init(struct camif_dev *camif) |
309 | { | 309 | { |
310 | struct media_device *md = &camif->media_dev; | 310 | struct media_device *md = &camif->media_dev; |
311 | struct v4l2_device *v4l2_dev = &camif->v4l2_dev; | 311 | struct v4l2_device *v4l2_dev = &camif->v4l2_dev; |
@@ -324,14 +324,12 @@ static int camif_media_dev_register(struct camif_dev *camif) | |||
324 | strlcpy(v4l2_dev->name, "s3c-camif", sizeof(v4l2_dev->name)); | 324 | strlcpy(v4l2_dev->name, "s3c-camif", sizeof(v4l2_dev->name)); |
325 | v4l2_dev->mdev = md; | 325 | v4l2_dev->mdev = md; |
326 | 326 | ||
327 | media_device_init(md); | ||
328 | |||
327 | ret = v4l2_device_register(camif->dev, v4l2_dev); | 329 | ret = v4l2_device_register(camif->dev, v4l2_dev); |
328 | if (ret < 0) | 330 | if (ret < 0) |
329 | return ret; | 331 | return ret; |
330 | 332 | ||
331 | ret = media_device_register(md); | ||
332 | if (ret < 0) | ||
333 | v4l2_device_unregister(v4l2_dev); | ||
334 | |||
335 | return ret; | 333 | return ret; |
336 | } | 334 | } |
337 | 335 | ||
@@ -483,7 +481,7 @@ static int s3c_camif_probe(struct platform_device *pdev) | |||
483 | goto err_alloc; | 481 | goto err_alloc; |
484 | } | 482 | } |
485 | 483 | ||
486 | ret = camif_media_dev_register(camif); | 484 | ret = camif_media_dev_init(camif); |
487 | if (ret < 0) | 485 | if (ret < 0) |
488 | goto err_mdev; | 486 | goto err_mdev; |
489 | 487 | ||
@@ -510,6 +508,11 @@ static int s3c_camif_probe(struct platform_device *pdev) | |||
510 | goto err_unlock; | 508 | goto err_unlock; |
511 | 509 | ||
512 | mutex_unlock(&camif->media_dev.graph_mutex); | 510 | mutex_unlock(&camif->media_dev.graph_mutex); |
511 | |||
512 | ret = media_device_register(&camif->media_dev); | ||
513 | if (ret < 0) | ||
514 | goto err_sens; | ||
515 | |||
513 | pm_runtime_put(dev); | 516 | pm_runtime_put(dev); |
514 | return 0; | 517 | return 0; |
515 | 518 | ||
@@ -518,6 +521,7 @@ err_unlock: | |||
518 | err_sens: | 521 | err_sens: |
519 | v4l2_device_unregister(&camif->v4l2_dev); | 522 | v4l2_device_unregister(&camif->v4l2_dev); |
520 | media_device_unregister(&camif->media_dev); | 523 | media_device_unregister(&camif->media_dev); |
524 | media_device_cleanup(&camif->media_dev); | ||
521 | camif_unregister_media_entities(camif); | 525 | camif_unregister_media_entities(camif); |
522 | err_mdev: | 526 | err_mdev: |
523 | vb2_dma_contig_cleanup_ctx(camif->alloc_ctx); | 527 | vb2_dma_contig_cleanup_ctx(camif->alloc_ctx); |
@@ -539,6 +543,7 @@ static int s3c_camif_remove(struct platform_device *pdev) | |||
539 | struct s3c_camif_plat_data *pdata = &camif->pdata; | 543 | struct s3c_camif_plat_data *pdata = &camif->pdata; |
540 | 544 | ||
541 | media_device_unregister(&camif->media_dev); | 545 | media_device_unregister(&camif->media_dev); |
546 | media_device_cleanup(&camif->media_dev); | ||
542 | camif_unregister_media_entities(camif); | 547 | camif_unregister_media_entities(camif); |
543 | v4l2_device_unregister(&camif->v4l2_dev); | 548 | v4l2_device_unregister(&camif->v4l2_dev); |
544 | 549 | ||
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 4e61886384e3..42dff9d020af 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c | |||
@@ -101,7 +101,7 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) | |||
101 | if (!(entity->pads[pad].flags & MEDIA_PAD_FL_SINK)) | 101 | if (!(entity->pads[pad].flags & MEDIA_PAD_FL_SINK)) |
102 | continue; | 102 | continue; |
103 | 103 | ||
104 | ret = media_entity_create_link(&source->subdev.entity, | 104 | ret = media_create_pad_link(&source->subdev.entity, |
105 | source->source_pad, | 105 | source->source_pad, |
106 | entity, pad, flags); | 106 | entity, pad, flags); |
107 | if (ret < 0) | 107 | if (ret < 0) |
@@ -127,6 +127,7 @@ static void vsp1_destroy_entities(struct vsp1_device *vsp1) | |||
127 | 127 | ||
128 | v4l2_device_unregister(&vsp1->v4l2_dev); | 128 | v4l2_device_unregister(&vsp1->v4l2_dev); |
129 | media_device_unregister(&vsp1->media_dev); | 129 | media_device_unregister(&vsp1->media_dev); |
130 | media_device_cleanup(&vsp1->media_dev); | ||
130 | } | 131 | } |
131 | 132 | ||
132 | static int vsp1_create_entities(struct vsp1_device *vsp1) | 133 | static int vsp1_create_entities(struct vsp1_device *vsp1) |
@@ -141,12 +142,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) | |||
141 | strlcpy(mdev->model, "VSP1", sizeof(mdev->model)); | 142 | strlcpy(mdev->model, "VSP1", sizeof(mdev->model)); |
142 | snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s", | 143 | snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s", |
143 | dev_name(mdev->dev)); | 144 | dev_name(mdev->dev)); |
144 | ret = media_device_register(mdev); | 145 | media_device_init(mdev); |
145 | if (ret < 0) { | ||
146 | dev_err(vsp1->dev, "media device registration failed (%d)\n", | ||
147 | ret); | ||
148 | return ret; | ||
149 | } | ||
150 | 146 | ||
151 | vdev->mdev = mdev; | 147 | vdev->mdev = mdev; |
152 | ret = v4l2_device_register(vsp1->dev, vdev); | 148 | ret = v4l2_device_register(vsp1->dev, vdev); |
@@ -250,34 +246,44 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) | |||
250 | list_add_tail(&wpf->entity.list_dev, &vsp1->entities); | 246 | list_add_tail(&wpf->entity.list_dev, &vsp1->entities); |
251 | } | 247 | } |
252 | 248 | ||
253 | /* Create links. */ | 249 | /* Register all subdevs. */ |
254 | list_for_each_entry(entity, &vsp1->entities, list_dev) { | 250 | list_for_each_entry(entity, &vsp1->entities, list_dev) { |
255 | if (entity->type == VSP1_ENTITY_LIF || | 251 | ret = v4l2_device_register_subdev(&vsp1->v4l2_dev, |
256 | entity->type == VSP1_ENTITY_RPF) | 252 | &entity->subdev); |
257 | continue; | ||
258 | |||
259 | ret = vsp1_create_links(vsp1, entity); | ||
260 | if (ret < 0) | 253 | if (ret < 0) |
261 | goto done; | 254 | goto done; |
262 | } | 255 | } |
263 | 256 | ||
257 | /* Create links. */ | ||
258 | list_for_each_entry(entity, &vsp1->entities, list_dev) { | ||
259 | if (entity->type == VSP1_ENTITY_LIF) { | ||
260 | ret = vsp1_wpf_create_links(vsp1, entity); | ||
261 | if (ret < 0) | ||
262 | goto done; | ||
263 | } else if (entity->type == VSP1_ENTITY_RPF) { | ||
264 | ret = vsp1_rpf_create_links(vsp1, entity); | ||
265 | if (ret < 0) | ||
266 | goto done; | ||
267 | } else { | ||
268 | ret = vsp1_create_links(vsp1, entity); | ||
269 | if (ret < 0) | ||
270 | goto done; | ||
271 | } | ||
272 | } | ||
273 | |||
264 | if (vsp1->pdata.features & VSP1_HAS_LIF) { | 274 | if (vsp1->pdata.features & VSP1_HAS_LIF) { |
265 | ret = media_entity_create_link( | 275 | ret = media_create_pad_link( |
266 | &vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE, | 276 | &vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE, |
267 | &vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0); | 277 | &vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0); |
268 | if (ret < 0) | 278 | if (ret < 0) |
269 | return ret; | 279 | return ret; |
270 | } | 280 | } |
271 | 281 | ||
272 | /* Register all subdevs. */ | ||
273 | list_for_each_entry(entity, &vsp1->entities, list_dev) { | ||
274 | ret = v4l2_device_register_subdev(&vsp1->v4l2_dev, | ||
275 | &entity->subdev); | ||
276 | if (ret < 0) | ||
277 | goto done; | ||
278 | } | ||
279 | |||
280 | ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); | 282 | ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); |
283 | if (ret < 0) | ||
284 | goto done; | ||
285 | |||
286 | ret = media_device_register(mdev); | ||
281 | 287 | ||
282 | done: | 288 | done: |
283 | if (ret < 0) | 289 | if (ret < 0) |
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index fd95a75b04f4..d7308530952f 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c | |||
@@ -219,8 +219,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, | |||
219 | entity->pads[num_pads - 1].flags = MEDIA_PAD_FL_SOURCE; | 219 | entity->pads[num_pads - 1].flags = MEDIA_PAD_FL_SOURCE; |
220 | 220 | ||
221 | /* Initialize the media entity. */ | 221 | /* Initialize the media entity. */ |
222 | return media_entity_init(&entity->subdev.entity, num_pads, | 222 | return media_entity_pads_init(&entity->subdev.entity, num_pads, |
223 | entity->pads, 0); | 223 | entity->pads); |
224 | } | 224 | } |
225 | 225 | ||
226 | void vsp1_entity_destroy(struct vsp1_entity *entity) | 226 | void vsp1_entity_destroy(struct vsp1_entity *entity) |
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index cd5248a9a271..924538223d3e 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c | |||
@@ -277,18 +277,29 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
277 | 277 | ||
278 | rpf->entity.video = video; | 278 | rpf->entity.video = video; |
279 | 279 | ||
280 | /* Connect the video device to the RPF. */ | ||
281 | ret = media_entity_create_link(&rpf->video.video.entity, 0, | ||
282 | &rpf->entity.subdev.entity, | ||
283 | RWPF_PAD_SINK, | ||
284 | MEDIA_LNK_FL_ENABLED | | ||
285 | MEDIA_LNK_FL_IMMUTABLE); | ||
286 | if (ret < 0) | ||
287 | goto error; | ||
288 | |||
289 | return rpf; | 280 | return rpf; |
290 | 281 | ||
291 | error: | 282 | error: |
292 | vsp1_entity_destroy(&rpf->entity); | 283 | vsp1_entity_destroy(&rpf->entity); |
293 | return ERR_PTR(ret); | 284 | return ERR_PTR(ret); |
294 | } | 285 | } |
286 | |||
287 | /* | ||
288 | * vsp1_rpf_create_links() - RPF pads links creation | ||
289 | * @vsp1: Pointer to VSP1 device | ||
290 | * @entity: Pointer to VSP1 entity | ||
291 | * | ||
292 | * return negative error code or zero on success | ||
293 | */ | ||
294 | int vsp1_rpf_create_links(struct vsp1_device *vsp1, | ||
295 | struct vsp1_entity *entity) | ||
296 | { | ||
297 | struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); | ||
298 | |||
299 | /* Connect the video device to the RPF. */ | ||
300 | return media_create_pad_link(&rpf->video.video.entity, 0, | ||
301 | &rpf->entity.subdev.entity, | ||
302 | RWPF_PAD_SINK, | ||
303 | MEDIA_LNK_FL_ENABLED | | ||
304 | MEDIA_LNK_FL_IMMUTABLE); | ||
305 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index f452dce1a931..731d36e5258d 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h | |||
@@ -50,6 +50,11 @@ static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) | |||
50 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); | 50 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); |
51 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); | 51 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); |
52 | 52 | ||
53 | int vsp1_rpf_create_links(struct vsp1_device *vsp1, | ||
54 | struct vsp1_entity *entity); | ||
55 | int vsp1_wpf_create_links(struct vsp1_device *vsp1, | ||
56 | struct vsp1_entity *entity); | ||
57 | |||
53 | int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, | 58 | int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, |
54 | struct v4l2_subdev_pad_config *cfg, | 59 | struct v4l2_subdev_pad_config *cfg, |
55 | struct v4l2_subdev_mbus_code_enum *code); | 60 | struct v4l2_subdev_mbus_code_enum *code); |
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 45eb65fa23db..637d0d6f79fb 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c | |||
@@ -160,8 +160,7 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad) | |||
160 | struct media_pad *remote; | 160 | struct media_pad *remote; |
161 | 161 | ||
162 | remote = media_entity_remote_pad(local); | 162 | remote = media_entity_remote_pad(local); |
163 | if (remote == NULL || | 163 | if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) |
164 | media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
165 | return NULL; | 164 | return NULL; |
166 | 165 | ||
167 | if (pad) | 166 | if (pad) |
@@ -283,24 +282,35 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe, | |||
283 | struct vsp1_rwpf *output) | 282 | struct vsp1_rwpf *output) |
284 | { | 283 | { |
285 | struct vsp1_entity *entity; | 284 | struct vsp1_entity *entity; |
286 | unsigned int entities = 0; | 285 | struct media_entity_enum ent_enum; |
287 | struct media_pad *pad; | 286 | struct media_pad *pad; |
287 | int rval; | ||
288 | bool bru_found = false; | 288 | bool bru_found = false; |
289 | 289 | ||
290 | input->location.left = 0; | 290 | input->location.left = 0; |
291 | input->location.top = 0; | 291 | input->location.top = 0; |
292 | 292 | ||
293 | rval = media_entity_enum_init( | ||
294 | &ent_enum, input->entity.pads[RWPF_PAD_SOURCE].graph_obj.mdev); | ||
295 | if (rval) | ||
296 | return rval; | ||
297 | |||
293 | pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); | 298 | pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); |
294 | 299 | ||
295 | while (1) { | 300 | while (1) { |
296 | if (pad == NULL) | 301 | if (pad == NULL) { |
297 | return -EPIPE; | 302 | rval = -EPIPE; |
303 | goto out; | ||
304 | } | ||
298 | 305 | ||
299 | /* We've reached a video node, that shouldn't have happened. */ | 306 | /* We've reached a video node, that shouldn't have happened. */ |
300 | if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | 307 | if (!is_media_entity_v4l2_subdev(pad->entity)) { |
301 | return -EPIPE; | 308 | rval = -EPIPE; |
309 | goto out; | ||
310 | } | ||
302 | 311 | ||
303 | entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); | 312 | entity = to_vsp1_entity( |
313 | media_entity_to_v4l2_subdev(pad->entity)); | ||
304 | 314 | ||
305 | /* A BRU is present in the pipeline, store the compose rectangle | 315 | /* A BRU is present in the pipeline, store the compose rectangle |
306 | * location in the input RPF for use when configuring the RPF. | 316 | * location in the input RPF for use when configuring the RPF. |
@@ -323,15 +333,18 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe, | |||
323 | break; | 333 | break; |
324 | 334 | ||
325 | /* Ensure the branch has no loop. */ | 335 | /* Ensure the branch has no loop. */ |
326 | if (entities & (1 << entity->subdev.entity.id)) | 336 | if (media_entity_enum_test_and_set(&ent_enum, |
327 | return -EPIPE; | 337 | &entity->subdev.entity)) { |
328 | 338 | rval = -EPIPE; | |
329 | entities |= 1 << entity->subdev.entity.id; | 339 | goto out; |
340 | } | ||
330 | 341 | ||
331 | /* UDS can't be chained. */ | 342 | /* UDS can't be chained. */ |
332 | if (entity->type == VSP1_ENTITY_UDS) { | 343 | if (entity->type == VSP1_ENTITY_UDS) { |
333 | if (pipe->uds) | 344 | if (pipe->uds) { |
334 | return -EPIPE; | 345 | rval = -EPIPE; |
346 | goto out; | ||
347 | } | ||
335 | 348 | ||
336 | pipe->uds = entity; | 349 | pipe->uds = entity; |
337 | pipe->uds_input = bru_found ? pipe->bru | 350 | pipe->uds_input = bru_found ? pipe->bru |
@@ -349,9 +362,12 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe, | |||
349 | 362 | ||
350 | /* The last entity must be the output WPF. */ | 363 | /* The last entity must be the output WPF. */ |
351 | if (entity != &output->entity) | 364 | if (entity != &output->entity) |
352 | return -EPIPE; | 365 | rval = -EPIPE; |
353 | 366 | ||
354 | return 0; | 367 | out: |
368 | media_entity_enum_cleanup(&ent_enum); | ||
369 | |||
370 | return rval; | ||
355 | } | 371 | } |
356 | 372 | ||
357 | static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) | 373 | static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) |
@@ -380,13 +396,19 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | |||
380 | { | 396 | { |
381 | struct media_entity_graph graph; | 397 | struct media_entity_graph graph; |
382 | struct media_entity *entity = &video->video.entity; | 398 | struct media_entity *entity = &video->video.entity; |
383 | struct media_device *mdev = entity->parent; | 399 | struct media_device *mdev = entity->graph_obj.mdev; |
384 | unsigned int i; | 400 | unsigned int i; |
385 | int ret; | 401 | int ret; |
386 | 402 | ||
387 | mutex_lock(&mdev->graph_mutex); | 403 | mutex_lock(&mdev->graph_mutex); |
388 | 404 | ||
389 | /* Walk the graph to locate the entities and video nodes. */ | 405 | /* Walk the graph to locate the entities and video nodes. */ |
406 | ret = media_entity_graph_walk_init(&graph, mdev); | ||
407 | if (ret) { | ||
408 | mutex_unlock(&mdev->graph_mutex); | ||
409 | return ret; | ||
410 | } | ||
411 | |||
390 | media_entity_graph_walk_start(&graph, entity); | 412 | media_entity_graph_walk_start(&graph, entity); |
391 | 413 | ||
392 | while ((entity = media_entity_graph_walk_next(&graph))) { | 414 | while ((entity = media_entity_graph_walk_next(&graph))) { |
@@ -394,7 +416,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | |||
394 | struct vsp1_rwpf *rwpf; | 416 | struct vsp1_rwpf *rwpf; |
395 | struct vsp1_entity *e; | 417 | struct vsp1_entity *e; |
396 | 418 | ||
397 | if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) { | 419 | if (is_media_entity_v4l2_io(entity)) { |
398 | pipe->num_video++; | 420 | pipe->num_video++; |
399 | continue; | 421 | continue; |
400 | } | 422 | } |
@@ -420,6 +442,8 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | |||
420 | 442 | ||
421 | mutex_unlock(&mdev->graph_mutex); | 443 | mutex_unlock(&mdev->graph_mutex); |
422 | 444 | ||
445 | media_entity_graph_walk_cleanup(&graph); | ||
446 | |||
423 | /* We need one output and at least one input. */ | 447 | /* We need one output and at least one input. */ |
424 | if (pipe->num_inputs == 0 || !pipe->output) { | 448 | if (pipe->num_inputs == 0 || !pipe->output) { |
425 | ret = -EPIPE; | 449 | ret = -EPIPE; |
@@ -663,7 +687,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, | |||
663 | pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]); | 687 | pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]); |
664 | 688 | ||
665 | while (pad) { | 689 | while (pad) { |
666 | if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | 690 | if (!is_media_entity_v4l2_subdev(pad->entity)) |
667 | break; | 691 | break; |
668 | 692 | ||
669 | entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); | 693 | entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); |
@@ -1193,7 +1217,7 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf) | |||
1193 | video->pipe.state = VSP1_PIPELINE_STOPPED; | 1217 | video->pipe.state = VSP1_PIPELINE_STOPPED; |
1194 | 1218 | ||
1195 | /* Initialize the media entity... */ | 1219 | /* Initialize the media entity... */ |
1196 | ret = media_entity_init(&video->video.entity, 1, &video->pad, 0); | 1220 | ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); |
1197 | if (ret < 0) | 1221 | if (ret < 0) |
1198 | return ret; | 1222 | return ret; |
1199 | 1223 | ||
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 95b62f4f77e7..cbf514a6582d 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c | |||
@@ -220,7 +220,6 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
220 | struct v4l2_subdev *subdev; | 220 | struct v4l2_subdev *subdev; |
221 | struct vsp1_video *video; | 221 | struct vsp1_video *video; |
222 | struct vsp1_rwpf *wpf; | 222 | struct vsp1_rwpf *wpf; |
223 | unsigned int flags; | ||
224 | int ret; | 223 | int ret; |
225 | 224 | ||
226 | wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); | 225 | wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); |
@@ -276,20 +275,6 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | |||
276 | goto error; | 275 | goto error; |
277 | 276 | ||
278 | wpf->entity.video = video; | 277 | wpf->entity.video = video; |
279 | |||
280 | /* Connect the video device to the WPF. All connections are immutable | ||
281 | * except for the WPF0 source link if a LIF is present. | ||
282 | */ | ||
283 | flags = MEDIA_LNK_FL_ENABLED; | ||
284 | if (!(vsp1->pdata.features & VSP1_HAS_LIF) || index != 0) | ||
285 | flags |= MEDIA_LNK_FL_IMMUTABLE; | ||
286 | |||
287 | ret = media_entity_create_link(&wpf->entity.subdev.entity, | ||
288 | RWPF_PAD_SOURCE, | ||
289 | &wpf->video.video.entity, 0, flags); | ||
290 | if (ret < 0) | ||
291 | goto error; | ||
292 | |||
293 | wpf->entity.sink = &wpf->video.video.entity; | 278 | wpf->entity.sink = &wpf->video.video.entity; |
294 | 279 | ||
295 | return wpf; | 280 | return wpf; |
@@ -298,3 +283,28 @@ error: | |||
298 | vsp1_entity_destroy(&wpf->entity); | 283 | vsp1_entity_destroy(&wpf->entity); |
299 | return ERR_PTR(ret); | 284 | return ERR_PTR(ret); |
300 | } | 285 | } |
286 | |||
287 | /* | ||
288 | * vsp1_wpf_create_links() - RPF pads links creation | ||
289 | * @vsp1: Pointer to VSP1 device | ||
290 | * @entity: Pointer to VSP1 entity | ||
291 | * | ||
292 | * return negative error code or zero on success | ||
293 | */ | ||
294 | int vsp1_wpf_create_links(struct vsp1_device *vsp1, | ||
295 | struct vsp1_entity *entity) | ||
296 | { | ||
297 | struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); | ||
298 | unsigned int flags; | ||
299 | |||
300 | /* Connect the video device to the WPF. All connections are immutable | ||
301 | * except for the WPF0 source link if a LIF is present. | ||
302 | */ | ||
303 | flags = MEDIA_LNK_FL_ENABLED; | ||
304 | if (!(vsp1->pdata.features & VSP1_HAS_LIF) || entity->index != 0) | ||
305 | flags |= MEDIA_LNK_FL_IMMUTABLE; | ||
306 | |||
307 | return media_create_pad_link(&wpf->entity.subdev.entity, | ||
308 | RWPF_PAD_SOURCE, | ||
309 | &wpf->video.video.entity, 0, flags); | ||
310 | } | ||
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c index 722758f33924..7f6898b13cac 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.c +++ b/drivers/media/platform/xilinx/xilinx-dma.c | |||
@@ -49,8 +49,7 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad) | |||
49 | struct media_pad *remote; | 49 | struct media_pad *remote; |
50 | 50 | ||
51 | remote = media_entity_remote_pad(local); | 51 | remote = media_entity_remote_pad(local); |
52 | if (remote == NULL || | 52 | if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) |
53 | media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
54 | return NULL; | 53 | return NULL; |
55 | 54 | ||
56 | if (pad) | 55 | if (pad) |
@@ -113,8 +112,7 @@ static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start) | |||
113 | break; | 112 | break; |
114 | 113 | ||
115 | pad = media_entity_remote_pad(pad); | 114 | pad = media_entity_remote_pad(pad); |
116 | if (pad == NULL || | 115 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
117 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
118 | break; | 116 | break; |
119 | 117 | ||
120 | entity = pad->entity; | 118 | entity = pad->entity; |
@@ -181,19 +179,26 @@ static int xvip_pipeline_validate(struct xvip_pipeline *pipe, | |||
181 | { | 179 | { |
182 | struct media_entity_graph graph; | 180 | struct media_entity_graph graph; |
183 | struct media_entity *entity = &start->video.entity; | 181 | struct media_entity *entity = &start->video.entity; |
184 | struct media_device *mdev = entity->parent; | 182 | struct media_device *mdev = entity->graph_obj.mdev; |
185 | unsigned int num_inputs = 0; | 183 | unsigned int num_inputs = 0; |
186 | unsigned int num_outputs = 0; | 184 | unsigned int num_outputs = 0; |
185 | int ret; | ||
187 | 186 | ||
188 | mutex_lock(&mdev->graph_mutex); | 187 | mutex_lock(&mdev->graph_mutex); |
189 | 188 | ||
190 | /* Walk the graph to locate the video nodes. */ | 189 | /* Walk the graph to locate the video nodes. */ |
190 | ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev); | ||
191 | if (ret) { | ||
192 | mutex_unlock(&mdev->graph_mutex); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
191 | media_entity_graph_walk_start(&graph, entity); | 196 | media_entity_graph_walk_start(&graph, entity); |
192 | 197 | ||
193 | while ((entity = media_entity_graph_walk_next(&graph))) { | 198 | while ((entity = media_entity_graph_walk_next(&graph))) { |
194 | struct xvip_dma *dma; | 199 | struct xvip_dma *dma; |
195 | 200 | ||
196 | if (entity->type != MEDIA_ENT_T_DEVNODE_V4L) | 201 | if (entity->function != MEDIA_ENT_F_IO_V4L) |
197 | continue; | 202 | continue; |
198 | 203 | ||
199 | dma = to_xvip_dma(media_entity_to_video_device(entity)); | 204 | dma = to_xvip_dma(media_entity_to_video_device(entity)); |
@@ -208,6 +213,8 @@ static int xvip_pipeline_validate(struct xvip_pipeline *pipe, | |||
208 | 213 | ||
209 | mutex_unlock(&mdev->graph_mutex); | 214 | mutex_unlock(&mdev->graph_mutex); |
210 | 215 | ||
216 | media_entity_graph_walk_cleanup(&graph); | ||
217 | |||
211 | /* We need exactly one output and zero or one input. */ | 218 | /* We need exactly one output and zero or one input. */ |
212 | if (num_outputs != 1 || num_inputs > 1) | 219 | if (num_outputs != 1 || num_inputs > 1) |
213 | return -EPIPE; | 220 | return -EPIPE; |
@@ -677,7 +684,7 @@ int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma, | |||
677 | dma->pad.flags = type == V4L2_BUF_TYPE_VIDEO_CAPTURE | 684 | dma->pad.flags = type == V4L2_BUF_TYPE_VIDEO_CAPTURE |
678 | ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; | 685 | ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; |
679 | 686 | ||
680 | ret = media_entity_init(&dma->video.entity, 1, &dma->pad, 0); | 687 | ret = media_entity_pads_init(&dma->video.entity, 1, &dma->pad); |
681 | if (ret < 0) | 688 | if (ret < 0) |
682 | goto error; | 689 | goto error; |
683 | 690 | ||
diff --git a/drivers/media/platform/xilinx/xilinx-tpg.c b/drivers/media/platform/xilinx/xilinx-tpg.c index 8bd7e3736019..2ec1f6c4b274 100644 --- a/drivers/media/platform/xilinx/xilinx-tpg.c +++ b/drivers/media/platform/xilinx/xilinx-tpg.c | |||
@@ -838,7 +838,7 @@ static int xtpg_probe(struct platform_device *pdev) | |||
838 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 838 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
839 | subdev->entity.ops = &xtpg_media_ops; | 839 | subdev->entity.ops = &xtpg_media_ops; |
840 | 840 | ||
841 | ret = media_entity_init(&subdev->entity, xtpg->npads, xtpg->pads, 0); | 841 | ret = media_entity_pads_init(&subdev->entity, xtpg->npads, xtpg->pads); |
842 | if (ret < 0) | 842 | if (ret < 0) |
843 | goto error; | 843 | goto error; |
844 | 844 | ||
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index b9bf24fefa5a..e795a4501e8b 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c | |||
@@ -156,7 +156,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, | |||
156 | local->name, local_pad->index, | 156 | local->name, local_pad->index, |
157 | remote->name, remote_pad->index); | 157 | remote->name, remote_pad->index); |
158 | 158 | ||
159 | ret = media_entity_create_link(local, local_pad->index, | 159 | ret = media_create_pad_link(local, local_pad->index, |
160 | remote, remote_pad->index, | 160 | remote, remote_pad->index, |
161 | link_flags); | 161 | link_flags); |
162 | if (ret < 0) { | 162 | if (ret < 0) { |
@@ -270,7 +270,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev) | |||
270 | source->name, source_pad->index, | 270 | source->name, source_pad->index, |
271 | sink->name, sink_pad->index); | 271 | sink->name, sink_pad->index); |
272 | 272 | ||
273 | ret = media_entity_create_link(source, source_pad->index, | 273 | ret = media_create_pad_link(source, source_pad->index, |
274 | sink, sink_pad->index, | 274 | sink, sink_pad->index, |
275 | link_flags); | 275 | link_flags); |
276 | if (ret < 0) { | 276 | if (ret < 0) { |
@@ -311,7 +311,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) | |||
311 | if (ret < 0) | 311 | if (ret < 0) |
312 | dev_err(xdev->dev, "failed to register subdev nodes\n"); | 312 | dev_err(xdev->dev, "failed to register subdev nodes\n"); |
313 | 313 | ||
314 | return ret; | 314 | return media_device_register(&xdev->media_dev); |
315 | } | 315 | } |
316 | 316 | ||
317 | static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier, | 317 | static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier, |
@@ -573,6 +573,7 @@ static void xvip_composite_v4l2_cleanup(struct xvip_composite_device *xdev) | |||
573 | { | 573 | { |
574 | v4l2_device_unregister(&xdev->v4l2_dev); | 574 | v4l2_device_unregister(&xdev->v4l2_dev); |
575 | media_device_unregister(&xdev->media_dev); | 575 | media_device_unregister(&xdev->media_dev); |
576 | media_device_cleanup(&xdev->media_dev); | ||
576 | } | 577 | } |
577 | 578 | ||
578 | static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev) | 579 | static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev) |
@@ -584,19 +585,14 @@ static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev) | |||
584 | sizeof(xdev->media_dev.model)); | 585 | sizeof(xdev->media_dev.model)); |
585 | xdev->media_dev.hw_revision = 0; | 586 | xdev->media_dev.hw_revision = 0; |
586 | 587 | ||
587 | ret = media_device_register(&xdev->media_dev); | 588 | media_device_init(&xdev->media_dev); |
588 | if (ret < 0) { | ||
589 | dev_err(xdev->dev, "media device registration failed (%d)\n", | ||
590 | ret); | ||
591 | return ret; | ||
592 | } | ||
593 | 589 | ||
594 | xdev->v4l2_dev.mdev = &xdev->media_dev; | 590 | xdev->v4l2_dev.mdev = &xdev->media_dev; |
595 | ret = v4l2_device_register(xdev->dev, &xdev->v4l2_dev); | 591 | ret = v4l2_device_register(xdev->dev, &xdev->v4l2_dev); |
596 | if (ret < 0) { | 592 | if (ret < 0) { |
597 | dev_err(xdev->dev, "V4L2 device registration failed (%d)\n", | 593 | dev_err(xdev->dev, "V4L2 device registration failed (%d)\n", |
598 | ret); | 594 | ret); |
599 | media_device_unregister(&xdev->media_dev); | 595 | media_device_cleanup(&xdev->media_dev); |
600 | return ret; | 596 | return ret; |
601 | } | 597 | } |
602 | 598 | ||
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c index 6b469e8c4c6e..ca861aea68a5 100644 --- a/drivers/media/usb/au0828/au0828-cards.c +++ b/drivers/media/usb/au0828/au0828-cards.c | |||
@@ -228,6 +228,10 @@ void au0828_card_analog_fe_setup(struct au0828_dev *dev) | |||
228 | "au8522", 0x8e >> 1, NULL); | 228 | "au8522", 0x8e >> 1, NULL); |
229 | if (sd == NULL) | 229 | if (sd == NULL) |
230 | pr_err("analog subdev registration failed\n"); | 230 | pr_err("analog subdev registration failed\n"); |
231 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
232 | if (sd) | ||
233 | dev->decoder = &sd->entity; | ||
234 | #endif | ||
231 | } | 235 | } |
232 | 236 | ||
233 | /* Setup tuners */ | 237 | /* Setup tuners */ |
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 0934024fb89d..9e29e70a78d7 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #include <media/v4l2-common.h> | 27 | #include <media/v4l2-common.h> |
28 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
29 | 29 | ||
30 | /* Due to enum tuner_pad_index */ | ||
31 | #include <media/tuner.h> | ||
32 | |||
30 | /* | 33 | /* |
31 | * 1 = General debug messages | 34 | * 1 = General debug messages |
32 | * 2 = USB handling | 35 | * 2 = USB handling |
@@ -127,8 +130,23 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, | |||
127 | return status; | 130 | return status; |
128 | } | 131 | } |
129 | 132 | ||
133 | static void au0828_unregister_media_device(struct au0828_dev *dev) | ||
134 | { | ||
135 | |||
136 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
137 | if (dev->media_dev) { | ||
138 | media_device_unregister(dev->media_dev); | ||
139 | media_device_cleanup(dev->media_dev); | ||
140 | kfree(dev->media_dev); | ||
141 | dev->media_dev = NULL; | ||
142 | } | ||
143 | #endif | ||
144 | } | ||
145 | |||
130 | static void au0828_usb_release(struct au0828_dev *dev) | 146 | static void au0828_usb_release(struct au0828_dev *dev) |
131 | { | 147 | { |
148 | au0828_unregister_media_device(dev); | ||
149 | |||
132 | /* I2C */ | 150 | /* I2C */ |
133 | au0828_i2c_unregister(dev); | 151 | au0828_i2c_unregister(dev); |
134 | 152 | ||
@@ -136,6 +154,20 @@ static void au0828_usb_release(struct au0828_dev *dev) | |||
136 | } | 154 | } |
137 | 155 | ||
138 | #ifdef CONFIG_VIDEO_AU0828_V4L2 | 156 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
157 | |||
158 | static void au0828_usb_v4l2_media_release(struct au0828_dev *dev) | ||
159 | { | ||
160 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
161 | int i; | ||
162 | |||
163 | for (i = 0; i < AU0828_MAX_INPUT; i++) { | ||
164 | if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) | ||
165 | return; | ||
166 | media_device_unregister_entity(&dev->input_ent[i]); | ||
167 | } | ||
168 | #endif | ||
169 | } | ||
170 | |||
139 | static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) | 171 | static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) |
140 | { | 172 | { |
141 | struct au0828_dev *dev = | 173 | struct au0828_dev *dev = |
@@ -143,6 +175,7 @@ static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) | |||
143 | 175 | ||
144 | v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); | 176 | v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); |
145 | v4l2_device_unregister(&dev->v4l2_dev); | 177 | v4l2_device_unregister(&dev->v4l2_dev); |
178 | au0828_usb_v4l2_media_release(dev); | ||
146 | au0828_usb_release(dev); | 179 | au0828_usb_release(dev); |
147 | } | 180 | } |
148 | #endif | 181 | #endif |
@@ -174,12 +207,123 @@ static void au0828_usb_disconnect(struct usb_interface *interface) | |||
174 | au0828_analog_unregister(dev); | 207 | au0828_analog_unregister(dev); |
175 | v4l2_device_disconnect(&dev->v4l2_dev); | 208 | v4l2_device_disconnect(&dev->v4l2_dev); |
176 | v4l2_device_put(&dev->v4l2_dev); | 209 | v4l2_device_put(&dev->v4l2_dev); |
210 | /* | ||
211 | * No need to call au0828_usb_release() if V4L2 is enabled, | ||
212 | * as this is already called via au0828_usb_v4l2_release() | ||
213 | */ | ||
177 | return; | 214 | return; |
178 | } | 215 | } |
179 | #endif | 216 | #endif |
180 | au0828_usb_release(dev); | 217 | au0828_usb_release(dev); |
181 | } | 218 | } |
182 | 219 | ||
220 | static int au0828_media_device_init(struct au0828_dev *dev, | ||
221 | struct usb_device *udev) | ||
222 | { | ||
223 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
224 | struct media_device *mdev; | ||
225 | |||
226 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); | ||
227 | if (!mdev) | ||
228 | return -ENOMEM; | ||
229 | |||
230 | mdev->dev = &udev->dev; | ||
231 | |||
232 | if (!dev->board.name) | ||
233 | strlcpy(mdev->model, "unknown au0828", sizeof(mdev->model)); | ||
234 | else | ||
235 | strlcpy(mdev->model, dev->board.name, sizeof(mdev->model)); | ||
236 | if (udev->serial) | ||
237 | strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); | ||
238 | strcpy(mdev->bus_info, udev->devpath); | ||
239 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | ||
240 | mdev->driver_version = LINUX_VERSION_CODE; | ||
241 | |||
242 | media_device_init(mdev); | ||
243 | |||
244 | dev->media_dev = mdev; | ||
245 | #endif | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | |||
250 | static int au0828_create_media_graph(struct au0828_dev *dev) | ||
251 | { | ||
252 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
253 | struct media_device *mdev = dev->media_dev; | ||
254 | struct media_entity *entity; | ||
255 | struct media_entity *tuner = NULL, *decoder = NULL; | ||
256 | int i, ret; | ||
257 | |||
258 | if (!mdev) | ||
259 | return 0; | ||
260 | |||
261 | media_device_for_each_entity(entity, mdev) { | ||
262 | switch (entity->function) { | ||
263 | case MEDIA_ENT_F_TUNER: | ||
264 | tuner = entity; | ||
265 | break; | ||
266 | case MEDIA_ENT_F_ATV_DECODER: | ||
267 | decoder = entity; | ||
268 | break; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | /* Analog setup, using tuner as a link */ | ||
273 | |||
274 | /* Something bad happened! */ | ||
275 | if (!decoder) | ||
276 | return -EINVAL; | ||
277 | |||
278 | if (tuner) { | ||
279 | ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, | ||
280 | decoder, 0, | ||
281 | MEDIA_LNK_FL_ENABLED); | ||
282 | if (ret) | ||
283 | return ret; | ||
284 | } | ||
285 | ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, | ||
286 | MEDIA_LNK_FL_ENABLED); | ||
287 | if (ret) | ||
288 | return ret; | ||
289 | ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, | ||
290 | MEDIA_LNK_FL_ENABLED); | ||
291 | if (ret) | ||
292 | return ret; | ||
293 | |||
294 | for (i = 0; i < AU0828_MAX_INPUT; i++) { | ||
295 | struct media_entity *ent = &dev->input_ent[i]; | ||
296 | |||
297 | if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) | ||
298 | break; | ||
299 | |||
300 | switch (AUVI_INPUT(i).type) { | ||
301 | case AU0828_VMUX_CABLE: | ||
302 | case AU0828_VMUX_TELEVISION: | ||
303 | case AU0828_VMUX_DVB: | ||
304 | if (!tuner) | ||
305 | break; | ||
306 | |||
307 | ret = media_create_pad_link(ent, 0, tuner, | ||
308 | TUNER_PAD_RF_INPUT, | ||
309 | MEDIA_LNK_FL_ENABLED); | ||
310 | if (ret) | ||
311 | return ret; | ||
312 | break; | ||
313 | case AU0828_VMUX_COMPOSITE: | ||
314 | case AU0828_VMUX_SVIDEO: | ||
315 | default: /* AU0828_VMUX_DEBUG */ | ||
316 | /* FIXME: fix the decoder PAD */ | ||
317 | ret = media_create_pad_link(ent, 0, decoder, 0, 0); | ||
318 | if (ret) | ||
319 | return ret; | ||
320 | break; | ||
321 | } | ||
322 | } | ||
323 | #endif | ||
324 | return 0; | ||
325 | } | ||
326 | |||
183 | static int au0828_usb_probe(struct usb_interface *interface, | 327 | static int au0828_usb_probe(struct usb_interface *interface, |
184 | const struct usb_device_id *id) | 328 | const struct usb_device_id *id) |
185 | { | 329 | { |
@@ -224,11 +368,23 @@ static int au0828_usb_probe(struct usb_interface *interface, | |||
224 | dev->boardnr = id->driver_info; | 368 | dev->boardnr = id->driver_info; |
225 | dev->board = au0828_boards[dev->boardnr]; | 369 | dev->board = au0828_boards[dev->boardnr]; |
226 | 370 | ||
371 | /* Initialize the media controller */ | ||
372 | retval = au0828_media_device_init(dev, usbdev); | ||
373 | if (retval) { | ||
374 | pr_err("%s() au0828_media_device_init failed\n", | ||
375 | __func__); | ||
376 | mutex_unlock(&dev->lock); | ||
377 | kfree(dev); | ||
378 | return retval; | ||
379 | } | ||
227 | 380 | ||
228 | #ifdef CONFIG_VIDEO_AU0828_V4L2 | 381 | #ifdef CONFIG_VIDEO_AU0828_V4L2 |
229 | dev->v4l2_dev.release = au0828_usb_v4l2_release; | 382 | dev->v4l2_dev.release = au0828_usb_v4l2_release; |
230 | 383 | ||
231 | /* Create the v4l2_device */ | 384 | /* Create the v4l2_device */ |
385 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
386 | dev->v4l2_dev.mdev = dev->media_dev; | ||
387 | #endif | ||
232 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); | 388 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
233 | if (retval) { | 389 | if (retval) { |
234 | pr_err("%s() v4l2_device_register failed\n", | 390 | pr_err("%s() v4l2_device_register failed\n", |
@@ -287,6 +443,21 @@ static int au0828_usb_probe(struct usb_interface *interface, | |||
287 | 443 | ||
288 | mutex_unlock(&dev->lock); | 444 | mutex_unlock(&dev->lock); |
289 | 445 | ||
446 | retval = au0828_create_media_graph(dev); | ||
447 | if (retval) { | ||
448 | pr_err("%s() au0282_dev_register failed to create graph\n", | ||
449 | __func__); | ||
450 | goto done; | ||
451 | } | ||
452 | |||
453 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
454 | retval = media_device_register(dev->media_dev); | ||
455 | #endif | ||
456 | |||
457 | done: | ||
458 | if (retval < 0) | ||
459 | au0828_usb_disconnect(interface); | ||
460 | |||
290 | return retval; | 461 | return retval; |
291 | } | 462 | } |
292 | 463 | ||
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index c267d76f5b3c..94363a3ba400 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c | |||
@@ -415,6 +415,11 @@ static int dvb_register(struct au0828_dev *dev) | |||
415 | result); | 415 | result); |
416 | goto fail_adapter; | 416 | goto fail_adapter; |
417 | } | 417 | } |
418 | |||
419 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||
420 | dvb->adapter.mdev = dev->media_dev; | ||
421 | #endif | ||
422 | |||
418 | dvb->adapter.priv = dev; | 423 | dvb->adapter.priv = dev; |
419 | 424 | ||
420 | /* register frontend */ | 425 | /* register frontend */ |
@@ -480,8 +485,15 @@ static int dvb_register(struct au0828_dev *dev) | |||
480 | 485 | ||
481 | dvb->start_count = 0; | 486 | dvb->start_count = 0; |
482 | dvb->stop_count = 0; | 487 | dvb->stop_count = 0; |
488 | |||
489 | result = dvb_create_media_graph(&dvb->adapter, false); | ||
490 | if (result < 0) | ||
491 | goto fail_create_graph; | ||
492 | |||
483 | return 0; | 493 | return 0; |
484 | 494 | ||
495 | fail_create_graph: | ||
496 | dvb_net_release(&dvb->net); | ||
485 | fail_fe_conn: | 497 | fail_fe_conn: |
486 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); | 498 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); |
487 | fail_fe_mem: | 499 | fail_fe_mem: |
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 0a725a161dd6..8c54fd21022e 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c | |||
@@ -638,6 +638,64 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | |||
638 | return rc; | 638 | return rc; |
639 | } | 639 | } |
640 | 640 | ||
641 | static int au0828_enable_analog_tuner(struct au0828_dev *dev) | ||
642 | { | ||
643 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
644 | struct media_device *mdev = dev->media_dev; | ||
645 | struct media_entity *source; | ||
646 | struct media_link *link, *found_link = NULL; | ||
647 | int ret, active_links = 0; | ||
648 | |||
649 | if (!mdev || !dev->decoder) | ||
650 | return 0; | ||
651 | |||
652 | /* | ||
653 | * This will find the tuner that is connected into the decoder. | ||
654 | * Technically, this is not 100% correct, as the device may be | ||
655 | * using an analog input instead of the tuner. However, as we can't | ||
656 | * do DVB streaming while the DMA engine is being used for V4L2, | ||
657 | * this should be enough for the actual needs. | ||
658 | */ | ||
659 | list_for_each_entry(link, &dev->decoder->links, list) { | ||
660 | if (link->sink->entity == dev->decoder) { | ||
661 | found_link = link; | ||
662 | if (link->flags & MEDIA_LNK_FL_ENABLED) | ||
663 | active_links++; | ||
664 | break; | ||
665 | } | ||
666 | } | ||
667 | |||
668 | if (active_links == 1 || !found_link) | ||
669 | return 0; | ||
670 | |||
671 | source = found_link->source->entity; | ||
672 | list_for_each_entry(link, &source->links, list) { | ||
673 | struct media_entity *sink; | ||
674 | int flags = 0; | ||
675 | |||
676 | sink = link->sink->entity; | ||
677 | |||
678 | if (sink == dev->decoder) | ||
679 | flags = MEDIA_LNK_FL_ENABLED; | ||
680 | |||
681 | ret = media_entity_setup_link(link, flags); | ||
682 | if (ret) { | ||
683 | pr_err( | ||
684 | "Couldn't change link %s->%s to %s. Error %d\n", | ||
685 | source->name, sink->name, | ||
686 | flags ? "enabled" : "disabled", | ||
687 | ret); | ||
688 | return ret; | ||
689 | } else | ||
690 | au0828_isocdbg( | ||
691 | "link %s->%s was %s\n", | ||
692 | source->name, sink->name, | ||
693 | flags ? "ENABLED" : "disabled"); | ||
694 | } | ||
695 | #endif | ||
696 | return 0; | ||
697 | } | ||
698 | |||
641 | static int queue_setup(struct vb2_queue *vq, | 699 | static int queue_setup(struct vb2_queue *vq, |
642 | unsigned int *nbuffers, unsigned int *nplanes, | 700 | unsigned int *nbuffers, unsigned int *nplanes, |
643 | unsigned int sizes[], void *alloc_ctxs[]) | 701 | unsigned int sizes[], void *alloc_ctxs[]) |
@@ -650,6 +708,8 @@ static int queue_setup(struct vb2_queue *vq, | |||
650 | *nplanes = 1; | 708 | *nplanes = 1; |
651 | sizes[0] = size; | 709 | sizes[0] = size; |
652 | 710 | ||
711 | au0828_enable_analog_tuner(dev); | ||
712 | |||
653 | return 0; | 713 | return 0; |
654 | } | 714 | } |
655 | 715 | ||
@@ -1735,6 +1795,69 @@ static int au0828_vb2_setup(struct au0828_dev *dev) | |||
1735 | return 0; | 1795 | return 0; |
1736 | } | 1796 | } |
1737 | 1797 | ||
1798 | static void au0828_analog_create_entities(struct au0828_dev *dev) | ||
1799 | { | ||
1800 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
1801 | static const char * const inames[] = { | ||
1802 | [AU0828_VMUX_COMPOSITE] = "Composite", | ||
1803 | [AU0828_VMUX_SVIDEO] = "S-Video", | ||
1804 | [AU0828_VMUX_CABLE] = "Cable TV", | ||
1805 | [AU0828_VMUX_TELEVISION] = "Television", | ||
1806 | [AU0828_VMUX_DVB] = "DVB", | ||
1807 | [AU0828_VMUX_DEBUG] = "tv debug" | ||
1808 | }; | ||
1809 | int ret, i; | ||
1810 | |||
1811 | /* Initialize Video and VBI pads */ | ||
1812 | dev->video_pad.flags = MEDIA_PAD_FL_SINK; | ||
1813 | ret = media_entity_pads_init(&dev->vdev.entity, 1, &dev->video_pad); | ||
1814 | if (ret < 0) | ||
1815 | pr_err("failed to initialize video media entity!\n"); | ||
1816 | |||
1817 | dev->vbi_pad.flags = MEDIA_PAD_FL_SINK; | ||
1818 | ret = media_entity_pads_init(&dev->vbi_dev.entity, 1, &dev->vbi_pad); | ||
1819 | if (ret < 0) | ||
1820 | pr_err("failed to initialize vbi media entity!\n"); | ||
1821 | |||
1822 | /* Create entities for each input connector */ | ||
1823 | for (i = 0; i < AU0828_MAX_INPUT; i++) { | ||
1824 | struct media_entity *ent = &dev->input_ent[i]; | ||
1825 | |||
1826 | if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) | ||
1827 | break; | ||
1828 | |||
1829 | ent->name = inames[AUVI_INPUT(i).type]; | ||
1830 | ent->flags = MEDIA_ENT_FL_CONNECTOR; | ||
1831 | dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; | ||
1832 | |||
1833 | switch (AUVI_INPUT(i).type) { | ||
1834 | case AU0828_VMUX_COMPOSITE: | ||
1835 | ent->function = MEDIA_ENT_F_CONN_COMPOSITE; | ||
1836 | break; | ||
1837 | case AU0828_VMUX_SVIDEO: | ||
1838 | ent->function = MEDIA_ENT_F_CONN_SVIDEO; | ||
1839 | break; | ||
1840 | case AU0828_VMUX_CABLE: | ||
1841 | case AU0828_VMUX_TELEVISION: | ||
1842 | case AU0828_VMUX_DVB: | ||
1843 | ent->function = MEDIA_ENT_F_CONN_RF; | ||
1844 | break; | ||
1845 | default: /* AU0828_VMUX_DEBUG */ | ||
1846 | ent->function = MEDIA_ENT_F_CONN_TEST; | ||
1847 | break; | ||
1848 | } | ||
1849 | |||
1850 | ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); | ||
1851 | if (ret < 0) | ||
1852 | pr_err("failed to initialize input pad[%d]!\n", i); | ||
1853 | |||
1854 | ret = media_device_register_entity(dev->media_dev, ent); | ||
1855 | if (ret < 0) | ||
1856 | pr_err("failed to register input entity %d!\n", i); | ||
1857 | } | ||
1858 | #endif | ||
1859 | } | ||
1860 | |||
1738 | /**************************************************************************/ | 1861 | /**************************************************************************/ |
1739 | 1862 | ||
1740 | int au0828_analog_register(struct au0828_dev *dev, | 1863 | int au0828_analog_register(struct au0828_dev *dev, |
@@ -1823,6 +1946,9 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1823 | dev->vbi_dev.queue->lock = &dev->vb_vbi_queue_lock; | 1946 | dev->vbi_dev.queue->lock = &dev->vb_vbi_queue_lock; |
1824 | strcpy(dev->vbi_dev.name, "au0828a vbi"); | 1947 | strcpy(dev->vbi_dev.name, "au0828a vbi"); |
1825 | 1948 | ||
1949 | /* Init entities at the Media Controller */ | ||
1950 | au0828_analog_create_entities(dev); | ||
1951 | |||
1826 | /* initialize videobuf2 stuff */ | 1952 | /* initialize videobuf2 stuff */ |
1827 | retval = au0828_vb2_setup(dev); | 1953 | retval = au0828_vb2_setup(dev); |
1828 | if (retval != 0) { | 1954 | if (retval != 0) { |
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 60b59391ea2a..8276072bc55a 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <media/v4l2-device.h> | 33 | #include <media/v4l2-device.h> |
34 | #include <media/v4l2-ctrls.h> | 34 | #include <media/v4l2-ctrls.h> |
35 | #include <media/v4l2-fh.h> | 35 | #include <media/v4l2-fh.h> |
36 | #include <media/media-device.h> | ||
36 | 37 | ||
37 | /* DVB */ | 38 | /* DVB */ |
38 | #include "demux.h" | 39 | #include "demux.h" |
@@ -93,7 +94,6 @@ struct au0828_board { | |||
93 | unsigned char has_ir_i2c:1; | 94 | unsigned char has_ir_i2c:1; |
94 | unsigned char has_analog:1; | 95 | unsigned char has_analog:1; |
95 | struct au0828_input input[AU0828_MAX_INPUT]; | 96 | struct au0828_input input[AU0828_MAX_INPUT]; |
96 | |||
97 | }; | 97 | }; |
98 | 98 | ||
99 | struct au0828_dvb { | 99 | struct au0828_dvb { |
@@ -276,6 +276,14 @@ struct au0828_dev { | |||
276 | /* Preallocated transfer digital transfer buffers */ | 276 | /* Preallocated transfer digital transfer buffers */ |
277 | 277 | ||
278 | char *dig_transfer_buffer[URB_COUNT]; | 278 | char *dig_transfer_buffer[URB_COUNT]; |
279 | |||
280 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
281 | struct media_device *media_dev; | ||
282 | struct media_pad video_pad, vbi_pad; | ||
283 | struct media_entity *decoder; | ||
284 | struct media_entity input_ent[AU0828_MAX_INPUT]; | ||
285 | struct media_pad input_pad[AU0828_MAX_INPUT]; | ||
286 | #endif | ||
279 | }; | 287 | }; |
280 | 288 | ||
281 | 289 | ||
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 89dc695c696e..620b83d03f75 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c | |||
@@ -1172,6 +1172,7 @@ static void cx231xx_unregister_media_device(struct cx231xx *dev) | |||
1172 | #ifdef CONFIG_MEDIA_CONTROLLER | 1172 | #ifdef CONFIG_MEDIA_CONTROLLER |
1173 | if (dev->media_dev) { | 1173 | if (dev->media_dev) { |
1174 | media_device_unregister(dev->media_dev); | 1174 | media_device_unregister(dev->media_dev); |
1175 | media_device_cleanup(dev->media_dev); | ||
1175 | kfree(dev->media_dev); | 1176 | kfree(dev->media_dev); |
1176 | dev->media_dev = NULL; | 1177 | dev->media_dev = NULL; |
1177 | } | 1178 | } |
@@ -1185,8 +1186,6 @@ static void cx231xx_unregister_media_device(struct cx231xx *dev) | |||
1185 | */ | 1186 | */ |
1186 | void cx231xx_release_resources(struct cx231xx *dev) | 1187 | void cx231xx_release_resources(struct cx231xx *dev) |
1187 | { | 1188 | { |
1188 | cx231xx_unregister_media_device(dev); | ||
1189 | |||
1190 | cx231xx_release_analog_resources(dev); | 1189 | cx231xx_release_analog_resources(dev); |
1191 | 1190 | ||
1192 | cx231xx_remove_from_devlist(dev); | 1191 | cx231xx_remove_from_devlist(dev); |
@@ -1199,22 +1198,23 @@ void cx231xx_release_resources(struct cx231xx *dev) | |||
1199 | /* delete v4l2 device */ | 1198 | /* delete v4l2 device */ |
1200 | v4l2_device_unregister(&dev->v4l2_dev); | 1199 | v4l2_device_unregister(&dev->v4l2_dev); |
1201 | 1200 | ||
1201 | cx231xx_unregister_media_device(dev); | ||
1202 | |||
1202 | usb_put_dev(dev->udev); | 1203 | usb_put_dev(dev->udev); |
1203 | 1204 | ||
1204 | /* Mark device as unused */ | 1205 | /* Mark device as unused */ |
1205 | clear_bit(dev->devno, &cx231xx_devused); | 1206 | clear_bit(dev->devno, &cx231xx_devused); |
1206 | } | 1207 | } |
1207 | 1208 | ||
1208 | static void cx231xx_media_device_register(struct cx231xx *dev, | 1209 | static int cx231xx_media_device_init(struct cx231xx *dev, |
1209 | struct usb_device *udev) | 1210 | struct usb_device *udev) |
1210 | { | 1211 | { |
1211 | #ifdef CONFIG_MEDIA_CONTROLLER | 1212 | #ifdef CONFIG_MEDIA_CONTROLLER |
1212 | struct media_device *mdev; | 1213 | struct media_device *mdev; |
1213 | int ret; | ||
1214 | 1214 | ||
1215 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); | 1215 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); |
1216 | if (!mdev) | 1216 | if (!mdev) |
1217 | return; | 1217 | return -ENOMEM; |
1218 | 1218 | ||
1219 | mdev->dev = dev->dev; | 1219 | mdev->dev = dev->dev; |
1220 | strlcpy(mdev->model, dev->board.name, sizeof(mdev->model)); | 1220 | strlcpy(mdev->model, dev->board.name, sizeof(mdev->model)); |
@@ -1224,35 +1224,30 @@ static void cx231xx_media_device_register(struct cx231xx *dev, | |||
1224 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | 1224 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); |
1225 | mdev->driver_version = LINUX_VERSION_CODE; | 1225 | mdev->driver_version = LINUX_VERSION_CODE; |
1226 | 1226 | ||
1227 | ret = media_device_register(mdev); | 1227 | media_device_init(mdev); |
1228 | if (ret) { | ||
1229 | dev_err(dev->dev, | ||
1230 | "Couldn't create a media device. Error: %d\n", | ||
1231 | ret); | ||
1232 | kfree(mdev); | ||
1233 | return; | ||
1234 | } | ||
1235 | 1228 | ||
1236 | dev->media_dev = mdev; | 1229 | dev->media_dev = mdev; |
1237 | #endif | 1230 | #endif |
1231 | return 0; | ||
1238 | } | 1232 | } |
1239 | 1233 | ||
1240 | static void cx231xx_create_media_graph(struct cx231xx *dev) | 1234 | static int cx231xx_create_media_graph(struct cx231xx *dev) |
1241 | { | 1235 | { |
1242 | #ifdef CONFIG_MEDIA_CONTROLLER | 1236 | #ifdef CONFIG_MEDIA_CONTROLLER |
1243 | struct media_device *mdev = dev->media_dev; | 1237 | struct media_device *mdev = dev->media_dev; |
1244 | struct media_entity *entity; | 1238 | struct media_entity *entity; |
1245 | struct media_entity *tuner = NULL, *decoder = NULL; | 1239 | struct media_entity *tuner = NULL, *decoder = NULL; |
1240 | int ret; | ||
1246 | 1241 | ||
1247 | if (!mdev) | 1242 | if (!mdev) |
1248 | return; | 1243 | return 0; |
1249 | 1244 | ||
1250 | media_device_for_each_entity(entity, mdev) { | 1245 | media_device_for_each_entity(entity, mdev) { |
1251 | switch (entity->type) { | 1246 | switch (entity->function) { |
1252 | case MEDIA_ENT_T_V4L2_SUBDEV_TUNER: | 1247 | case MEDIA_ENT_F_TUNER: |
1253 | tuner = entity; | 1248 | tuner = entity; |
1254 | break; | 1249 | break; |
1255 | case MEDIA_ENT_T_V4L2_SUBDEV_DECODER: | 1250 | case MEDIA_ENT_F_ATV_DECODER: |
1256 | decoder = entity; | 1251 | decoder = entity; |
1257 | break; | 1252 | break; |
1258 | } | 1253 | } |
@@ -1261,16 +1256,24 @@ static void cx231xx_create_media_graph(struct cx231xx *dev) | |||
1261 | /* Analog setup, using tuner as a link */ | 1256 | /* Analog setup, using tuner as a link */ |
1262 | 1257 | ||
1263 | if (!decoder) | 1258 | if (!decoder) |
1264 | return; | 1259 | return 0; |
1265 | 1260 | ||
1266 | if (tuner) | 1261 | if (tuner) { |
1267 | media_entity_create_link(tuner, 0, decoder, 0, | 1262 | ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, decoder, 0, |
1268 | MEDIA_LNK_FL_ENABLED); | 1263 | MEDIA_LNK_FL_ENABLED); |
1269 | media_entity_create_link(decoder, 1, &dev->vdev.entity, 0, | 1264 | if (ret < 0) |
1270 | MEDIA_LNK_FL_ENABLED); | 1265 | return ret; |
1271 | media_entity_create_link(decoder, 2, &dev->vbi_dev.entity, 0, | 1266 | } |
1272 | MEDIA_LNK_FL_ENABLED); | 1267 | ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, |
1268 | MEDIA_LNK_FL_ENABLED); | ||
1269 | if (ret < 0) | ||
1270 | return ret; | ||
1271 | ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, | ||
1272 | MEDIA_LNK_FL_ENABLED); | ||
1273 | if (ret < 0) | ||
1274 | return ret; | ||
1273 | #endif | 1275 | #endif |
1276 | return 0; | ||
1274 | } | 1277 | } |
1275 | 1278 | ||
1276 | /* | 1279 | /* |
@@ -1660,8 +1663,12 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1660 | /* save our data pointer in this interface device */ | 1663 | /* save our data pointer in this interface device */ |
1661 | usb_set_intfdata(interface, dev); | 1664 | usb_set_intfdata(interface, dev); |
1662 | 1665 | ||
1663 | /* Register the media controller */ | 1666 | /* Initialize the media controller */ |
1664 | cx231xx_media_device_register(dev, udev); | 1667 | retval = cx231xx_media_device_init(dev, udev); |
1668 | if (retval) { | ||
1669 | dev_err(d, "cx231xx_media_device_init failed\n"); | ||
1670 | goto err_media_init; | ||
1671 | } | ||
1665 | 1672 | ||
1666 | /* Create v4l2 device */ | 1673 | /* Create v4l2 device */ |
1667 | #ifdef CONFIG_MEDIA_CONTROLLER | 1674 | #ifdef CONFIG_MEDIA_CONTROLLER |
@@ -1732,9 +1739,19 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1732 | /* load other modules required */ | 1739 | /* load other modules required */ |
1733 | request_modules(dev); | 1740 | request_modules(dev); |
1734 | 1741 | ||
1735 | cx231xx_create_media_graph(dev); | 1742 | retval = cx231xx_create_media_graph(dev); |
1743 | if (retval < 0) | ||
1744 | goto done; | ||
1745 | |||
1746 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
1747 | retval = media_device_register(dev->media_dev); | ||
1748 | #endif | ||
1749 | |||
1750 | done: | ||
1751 | if (retval < 0) | ||
1752 | cx231xx_release_resources(dev); | ||
1753 | return retval; | ||
1736 | 1754 | ||
1737 | return 0; | ||
1738 | err_video_alt: | 1755 | err_video_alt: |
1739 | /* cx231xx_uninit_dev: */ | 1756 | /* cx231xx_uninit_dev: */ |
1740 | cx231xx_close_extension(dev); | 1757 | cx231xx_close_extension(dev); |
@@ -1746,6 +1763,8 @@ err_video_alt: | |||
1746 | err_init: | 1763 | err_init: |
1747 | v4l2_device_unregister(&dev->v4l2_dev); | 1764 | v4l2_device_unregister(&dev->v4l2_dev); |
1748 | err_v4l2: | 1765 | err_v4l2: |
1766 | cx231xx_unregister_media_device(dev); | ||
1767 | err_media_init: | ||
1749 | usb_set_intfdata(interface, NULL); | 1768 | usb_set_intfdata(interface, NULL); |
1750 | err_if: | 1769 | err_if: |
1751 | usb_put_dev(udev); | 1770 | usb_put_dev(udev); |
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index e3594b9fab4a..b8d5b2be9293 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c | |||
@@ -551,10 +551,14 @@ static int register_dvb(struct cx231xx_dvb *dvb, | |||
551 | 551 | ||
552 | /* register network adapter */ | 552 | /* register network adapter */ |
553 | dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); | 553 | dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); |
554 | dvb_create_media_graph(&dvb->adapter); | 554 | result = dvb_create_media_graph(&dvb->adapter, false); |
555 | if (result < 0) | ||
556 | goto fail_create_graph; | ||
555 | 557 | ||
556 | return 0; | 558 | return 0; |
557 | 559 | ||
560 | fail_create_graph: | ||
561 | dvb_net_release(&dvb->net); | ||
558 | fail_fe_conn: | 562 | fail_fe_conn: |
559 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); | 563 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); |
560 | fail_fe_mem: | 564 | fail_fe_mem: |
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index a70850fe6235..9b88cd8127ac 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c | |||
@@ -106,7 +106,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev) | |||
106 | struct media_device *mdev = dev->media_dev; | 106 | struct media_device *mdev = dev->media_dev; |
107 | struct media_entity *entity, *decoder = NULL, *source; | 107 | struct media_entity *entity, *decoder = NULL, *source; |
108 | struct media_link *link, *found_link = NULL; | 108 | struct media_link *link, *found_link = NULL; |
109 | int i, ret, active_links = 0; | 109 | int ret, active_links = 0; |
110 | 110 | ||
111 | if (!mdev) | 111 | if (!mdev) |
112 | return 0; | 112 | return 0; |
@@ -119,7 +119,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev) | |||
119 | * this should be enough for the actual needs. | 119 | * this should be enough for the actual needs. |
120 | */ | 120 | */ |
121 | media_device_for_each_entity(entity, mdev) { | 121 | media_device_for_each_entity(entity, mdev) { |
122 | if (entity->type == MEDIA_ENT_T_V4L2_SUBDEV_DECODER) { | 122 | if (entity->function == MEDIA_ENT_F_ATV_DECODER) { |
123 | decoder = entity; | 123 | decoder = entity; |
124 | break; | 124 | break; |
125 | } | 125 | } |
@@ -127,8 +127,7 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev) | |||
127 | if (!decoder) | 127 | if (!decoder) |
128 | return 0; | 128 | return 0; |
129 | 129 | ||
130 | for (i = 0; i < decoder->num_links; i++) { | 130 | list_for_each_entry(link, &decoder->links, list) { |
131 | link = &decoder->links[i]; | ||
132 | if (link->sink->entity == decoder) { | 131 | if (link->sink->entity == decoder) { |
133 | found_link = link; | 132 | found_link = link; |
134 | if (link->flags & MEDIA_LNK_FL_ENABLED) | 133 | if (link->flags & MEDIA_LNK_FL_ENABLED) |
@@ -141,11 +140,10 @@ static int cx231xx_enable_analog_tuner(struct cx231xx *dev) | |||
141 | return 0; | 140 | return 0; |
142 | 141 | ||
143 | source = found_link->source->entity; | 142 | source = found_link->source->entity; |
144 | for (i = 0; i < source->num_links; i++) { | 143 | list_for_each_entry(link, &source->links, list) { |
145 | struct media_entity *sink; | 144 | struct media_entity *sink; |
146 | int flags = 0; | 145 | int flags = 0; |
147 | 146 | ||
148 | link = &source->links[i]; | ||
149 | sink = link->sink->entity; | 147 | sink = link->sink->entity; |
150 | 148 | ||
151 | if (sink == entity) | 149 | if (sink == entity) |
@@ -2177,7 +2175,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) | |||
2177 | cx231xx_vdev_init(dev, &dev->vdev, &cx231xx_video_template, "video"); | 2175 | cx231xx_vdev_init(dev, &dev->vdev, &cx231xx_video_template, "video"); |
2178 | #if defined(CONFIG_MEDIA_CONTROLLER) | 2176 | #if defined(CONFIG_MEDIA_CONTROLLER) |
2179 | dev->video_pad.flags = MEDIA_PAD_FL_SINK; | 2177 | dev->video_pad.flags = MEDIA_PAD_FL_SINK; |
2180 | ret = media_entity_init(&dev->vdev.entity, 1, &dev->video_pad, 0); | 2178 | ret = media_entity_pads_init(&dev->vdev.entity, 1, &dev->video_pad); |
2181 | if (ret < 0) | 2179 | if (ret < 0) |
2182 | dev_err(dev->dev, "failed to initialize video media entity!\n"); | 2180 | dev_err(dev->dev, "failed to initialize video media entity!\n"); |
2183 | #endif | 2181 | #endif |
@@ -2204,7 +2202,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) | |||
2204 | 2202 | ||
2205 | #if defined(CONFIG_MEDIA_CONTROLLER) | 2203 | #if defined(CONFIG_MEDIA_CONTROLLER) |
2206 | dev->vbi_pad.flags = MEDIA_PAD_FL_SINK; | 2204 | dev->vbi_pad.flags = MEDIA_PAD_FL_SINK; |
2207 | ret = media_entity_init(&dev->vbi_dev.entity, 1, &dev->vbi_pad, 0); | 2205 | ret = media_entity_pads_init(&dev->vbi_dev.entity, 1, &dev->vbi_pad); |
2208 | if (ret < 0) | 2206 | if (ret < 0) |
2209 | dev_err(dev->dev, "failed to initialize vbi media entity!\n"); | 2207 | dev_err(dev->dev, "failed to initialize vbi media entity!\n"); |
2210 | #endif | 2208 | #endif |
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index f5df9eaba04f..f0565bf3673e 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | |||
@@ -400,17 +400,16 @@ skip_feed_stop: | |||
400 | return ret; | 400 | return ret; |
401 | } | 401 | } |
402 | 402 | ||
403 | static void dvb_usbv2_media_device_register(struct dvb_usb_adapter *adap) | 403 | static int dvb_usbv2_media_device_init(struct dvb_usb_adapter *adap) |
404 | { | 404 | { |
405 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | 405 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB |
406 | struct media_device *mdev; | 406 | struct media_device *mdev; |
407 | struct dvb_usb_device *d = adap_to_d(adap); | 407 | struct dvb_usb_device *d = adap_to_d(adap); |
408 | struct usb_device *udev = d->udev; | 408 | struct usb_device *udev = d->udev; |
409 | int ret; | ||
410 | 409 | ||
411 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); | 410 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); |
412 | if (!mdev) | 411 | if (!mdev) |
413 | return; | 412 | return -ENOMEM; |
414 | 413 | ||
415 | mdev->dev = &udev->dev; | 414 | mdev->dev = &udev->dev; |
416 | strlcpy(mdev->model, d->name, sizeof(mdev->model)); | 415 | strlcpy(mdev->model, d->name, sizeof(mdev->model)); |
@@ -420,19 +419,21 @@ static void dvb_usbv2_media_device_register(struct dvb_usb_adapter *adap) | |||
420 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | 419 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); |
421 | mdev->driver_version = LINUX_VERSION_CODE; | 420 | mdev->driver_version = LINUX_VERSION_CODE; |
422 | 421 | ||
423 | ret = media_device_register(mdev); | 422 | media_device_init(mdev); |
424 | if (ret) { | ||
425 | dev_err(&d->udev->dev, | ||
426 | "Couldn't create a media device. Error: %d\n", | ||
427 | ret); | ||
428 | kfree(mdev); | ||
429 | return; | ||
430 | } | ||
431 | 423 | ||
432 | dvb_register_media_controller(&adap->dvb_adap, mdev); | 424 | dvb_register_media_controller(&adap->dvb_adap, mdev); |
433 | 425 | ||
434 | dev_info(&d->udev->dev, "media controller created\n"); | 426 | dev_info(&d->udev->dev, "media controller created\n"); |
427 | #endif | ||
428 | return 0; | ||
429 | } | ||
435 | 430 | ||
431 | static int dvb_usbv2_media_device_register(struct dvb_usb_adapter *adap) | ||
432 | { | ||
433 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||
434 | return media_device_register(adap->dvb_adap.mdev); | ||
435 | #else | ||
436 | return 0; | ||
436 | #endif | 437 | #endif |
437 | } | 438 | } |
438 | 439 | ||
@@ -444,6 +445,7 @@ static void dvb_usbv2_media_device_unregister(struct dvb_usb_adapter *adap) | |||
444 | return; | 445 | return; |
445 | 446 | ||
446 | media_device_unregister(adap->dvb_adap.mdev); | 447 | media_device_unregister(adap->dvb_adap.mdev); |
448 | media_device_cleanup(adap->dvb_adap.mdev); | ||
447 | kfree(adap->dvb_adap.mdev); | 449 | kfree(adap->dvb_adap.mdev); |
448 | adap->dvb_adap.mdev = NULL; | 450 | adap->dvb_adap.mdev = NULL; |
449 | 451 | ||
@@ -467,7 +469,12 @@ static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) | |||
467 | 469 | ||
468 | adap->dvb_adap.priv = adap; | 470 | adap->dvb_adap.priv = adap; |
469 | 471 | ||
470 | dvb_usbv2_media_device_register(adap); | 472 | ret = dvb_usbv2_media_device_init(adap); |
473 | if (ret < 0) { | ||
474 | dev_dbg(&d->udev->dev, "%s: dvb_usbv2_media_device_init() failed=%d\n", | ||
475 | __func__, ret); | ||
476 | goto err_dvb_register_mc; | ||
477 | } | ||
471 | 478 | ||
472 | if (d->props->read_mac_address) { | 479 | if (d->props->read_mac_address) { |
473 | ret = d->props->read_mac_address(adap, | 480 | ret = d->props->read_mac_address(adap, |
@@ -518,6 +525,7 @@ err_dvb_dmxdev_init: | |||
518 | dvb_dmx_release(&adap->demux); | 525 | dvb_dmx_release(&adap->demux); |
519 | err_dvb_dmx_init: | 526 | err_dvb_dmx_init: |
520 | dvb_usbv2_media_device_unregister(adap); | 527 | dvb_usbv2_media_device_unregister(adap); |
528 | err_dvb_register_mc: | ||
521 | dvb_unregister_adapter(&adap->dvb_adap); | 529 | dvb_unregister_adapter(&adap->dvb_adap); |
522 | err_dvb_register_adapter: | 530 | err_dvb_register_adapter: |
523 | adap->dvb_adap.priv = NULL; | 531 | adap->dvb_adap.priv = NULL; |
@@ -534,7 +542,6 @@ static int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap) | |||
534 | adap->demux.dmx.close(&adap->demux.dmx); | 542 | adap->demux.dmx.close(&adap->demux.dmx); |
535 | dvb_dmxdev_release(&adap->dmxdev); | 543 | dvb_dmxdev_release(&adap->dmxdev); |
536 | dvb_dmx_release(&adap->demux); | 544 | dvb_dmx_release(&adap->demux); |
537 | dvb_usbv2_media_device_unregister(adap); | ||
538 | dvb_unregister_adapter(&adap->dvb_adap); | 545 | dvb_unregister_adapter(&adap->dvb_adap); |
539 | } | 546 | } |
540 | 547 | ||
@@ -698,9 +705,13 @@ static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) | |||
698 | } | 705 | } |
699 | } | 706 | } |
700 | 707 | ||
701 | dvb_create_media_graph(&adap->dvb_adap); | 708 | ret = dvb_create_media_graph(&adap->dvb_adap, true); |
709 | if (ret < 0) | ||
710 | goto err_dvb_unregister_frontend; | ||
702 | 711 | ||
703 | return 0; | 712 | ret = dvb_usbv2_media_device_register(adap); |
713 | |||
714 | return ret; | ||
704 | 715 | ||
705 | err_dvb_unregister_frontend: | 716 | err_dvb_unregister_frontend: |
706 | for (i = count_registered - 1; i >= 0; i--) | 717 | for (i = count_registered - 1; i >= 0; i--) |
@@ -840,6 +851,7 @@ static int dvb_usbv2_adapter_exit(struct dvb_usb_device *d) | |||
840 | dvb_usbv2_adapter_dvb_exit(&d->adapter[i]); | 851 | dvb_usbv2_adapter_dvb_exit(&d->adapter[i]); |
841 | dvb_usbv2_adapter_stream_exit(&d->adapter[i]); | 852 | dvb_usbv2_adapter_stream_exit(&d->adapter[i]); |
842 | dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); | 853 | dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); |
854 | dvb_usbv2_media_device_unregister(&d->adapter[i]); | ||
843 | } | 855 | } |
844 | } | 856 | } |
845 | 857 | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index 1710f9038d75..b669deccc34c 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/vmalloc.h> | 11 | #include <linux/vmalloc.h> |
12 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
13 | #include <media/tuner.h> | ||
13 | 14 | ||
14 | #include "mxl111sf.h" | 15 | #include "mxl111sf.h" |
15 | #include "mxl111sf-reg.h" | 16 | #include "mxl111sf-reg.h" |
@@ -868,6 +869,10 @@ static struct mxl111sf_tuner_config mxl_tuner_config = { | |||
868 | static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) | 869 | static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) |
869 | { | 870 | { |
870 | struct mxl111sf_state *state = adap_to_priv(adap); | 871 | struct mxl111sf_state *state = adap_to_priv(adap); |
872 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||
873 | struct media_device *mdev = dvb_get_media_controller(&adap->dvb_adap); | ||
874 | int ret; | ||
875 | #endif | ||
871 | int i; | 876 | int i; |
872 | 877 | ||
873 | pr_debug("%s()\n", __func__); | 878 | pr_debug("%s()\n", __func__); |
@@ -879,6 +884,21 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) | |||
879 | adap->fe[i]->ops.read_signal_strength = adap->fe[i]->ops.tuner_ops.get_rf_strength; | 884 | adap->fe[i]->ops.read_signal_strength = adap->fe[i]->ops.tuner_ops.get_rf_strength; |
880 | } | 885 | } |
881 | 886 | ||
887 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||
888 | state->tuner.function = MEDIA_ENT_F_TUNER; | ||
889 | state->tuner.name = "mxl111sf tuner"; | ||
890 | state->tuner_pads[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; | ||
891 | state->tuner_pads[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; | ||
892 | |||
893 | ret = media_entity_pads_init(&state->tuner, | ||
894 | TUNER_NUM_PADS, state->tuner_pads); | ||
895 | if (ret) | ||
896 | return ret; | ||
897 | |||
898 | ret = media_device_register_entity(mdev, &state->tuner); | ||
899 | if (ret) | ||
900 | return ret; | ||
901 | #endif | ||
882 | return 0; | 902 | return 0; |
883 | } | 903 | } |
884 | 904 | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h index ee70df1f1e94..846260e0eec0 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #define DVB_USB_LOG_PREFIX "mxl111sf" | 17 | #define DVB_USB_LOG_PREFIX "mxl111sf" |
18 | #include "dvb_usb.h" | 18 | #include "dvb_usb.h" |
19 | #include <media/tveeprom.h> | 19 | #include <media/tveeprom.h> |
20 | #include <media/media-entity.h> | ||
20 | 21 | ||
21 | #define MXL_EP1_REG_READ 1 | 22 | #define MXL_EP1_REG_READ 1 |
22 | #define MXL_EP2_REG_WRITE 2 | 23 | #define MXL_EP2_REG_WRITE 2 |
@@ -85,6 +86,10 @@ struct mxl111sf_state { | |||
85 | struct mutex fe_lock; | 86 | struct mutex fe_lock; |
86 | u8 num_frontends; | 87 | u8 num_frontends; |
87 | struct mxl111sf_adap_state adap_state[3]; | 88 | struct mxl111sf_adap_state adap_state[3]; |
89 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||
90 | struct media_entity tuner; | ||
91 | struct media_pad tuner_pads[2]; | ||
92 | #endif | ||
88 | }; | 93 | }; |
89 | 94 | ||
90 | int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data); | 95 | int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data); |
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 8a260c854653..9ddfcab268be 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c | |||
@@ -95,17 +95,16 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | |||
95 | return dvb_usb_ctrl_feed(dvbdmxfeed, 0); | 95 | return dvb_usb_ctrl_feed(dvbdmxfeed, 0); |
96 | } | 96 | } |
97 | 97 | ||
98 | static void dvb_usb_media_device_register(struct dvb_usb_adapter *adap) | 98 | static int dvb_usb_media_device_init(struct dvb_usb_adapter *adap) |
99 | { | 99 | { |
100 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | 100 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB |
101 | struct media_device *mdev; | 101 | struct media_device *mdev; |
102 | struct dvb_usb_device *d = adap->dev; | 102 | struct dvb_usb_device *d = adap->dev; |
103 | struct usb_device *udev = d->udev; | 103 | struct usb_device *udev = d->udev; |
104 | int ret; | ||
105 | 104 | ||
106 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); | 105 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); |
107 | if (!mdev) | 106 | if (!mdev) |
108 | return; | 107 | return -ENOMEM; |
109 | 108 | ||
110 | mdev->dev = &udev->dev; | 109 | mdev->dev = &udev->dev; |
111 | strlcpy(mdev->model, d->desc->name, sizeof(mdev->model)); | 110 | strlcpy(mdev->model, d->desc->name, sizeof(mdev->model)); |
@@ -115,18 +114,22 @@ static void dvb_usb_media_device_register(struct dvb_usb_adapter *adap) | |||
115 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | 114 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); |
116 | mdev->driver_version = LINUX_VERSION_CODE; | 115 | mdev->driver_version = LINUX_VERSION_CODE; |
117 | 116 | ||
118 | ret = media_device_register(mdev); | 117 | media_device_init(mdev); |
119 | if (ret) { | 118 | |
120 | dev_err(&d->udev->dev, | ||
121 | "Couldn't create a media device. Error: %d\n", | ||
122 | ret); | ||
123 | kfree(mdev); | ||
124 | return; | ||
125 | } | ||
126 | dvb_register_media_controller(&adap->dvb_adap, mdev); | 119 | dvb_register_media_controller(&adap->dvb_adap, mdev); |
127 | 120 | ||
128 | dev_info(&d->udev->dev, "media controller created\n"); | 121 | dev_info(&d->udev->dev, "media controller created\n"); |
129 | #endif | 122 | #endif |
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int dvb_usb_media_device_register(struct dvb_usb_adapter *adap) | ||
127 | { | ||
128 | #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||
129 | return media_device_register(adap->dvb_adap.mdev); | ||
130 | #else | ||
131 | return 0; | ||
132 | #endif | ||
130 | } | 133 | } |
131 | 134 | ||
132 | static void dvb_usb_media_device_unregister(struct dvb_usb_adapter *adap) | 135 | static void dvb_usb_media_device_unregister(struct dvb_usb_adapter *adap) |
@@ -136,6 +139,7 @@ static void dvb_usb_media_device_unregister(struct dvb_usb_adapter *adap) | |||
136 | return; | 139 | return; |
137 | 140 | ||
138 | media_device_unregister(adap->dvb_adap.mdev); | 141 | media_device_unregister(adap->dvb_adap.mdev); |
142 | media_device_cleanup(adap->dvb_adap.mdev); | ||
139 | kfree(adap->dvb_adap.mdev); | 143 | kfree(adap->dvb_adap.mdev); |
140 | adap->dvb_adap.mdev = NULL; | 144 | adap->dvb_adap.mdev = NULL; |
141 | #endif | 145 | #endif |
@@ -154,7 +158,11 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums) | |||
154 | } | 158 | } |
155 | adap->dvb_adap.priv = adap; | 159 | adap->dvb_adap.priv = adap; |
156 | 160 | ||
157 | dvb_usb_media_device_register(adap); | 161 | ret = dvb_usb_media_device_init(adap); |
162 | if (ret < 0) { | ||
163 | deb_info("dvb_usb_media_device_init failed: error %d", ret); | ||
164 | goto err_mc; | ||
165 | } | ||
158 | 166 | ||
159 | if (adap->dev->props.read_mac_address) { | 167 | if (adap->dev->props.read_mac_address) { |
160 | if (adap->dev->props.read_mac_address(adap->dev, adap->dvb_adap.proposed_mac) == 0) | 168 | if (adap->dev->props.read_mac_address(adap->dev, adap->dvb_adap.proposed_mac) == 0) |
@@ -204,6 +212,7 @@ err_dmx_dev: | |||
204 | dvb_dmx_release(&adap->demux); | 212 | dvb_dmx_release(&adap->demux); |
205 | err_dmx: | 213 | err_dmx: |
206 | dvb_usb_media_device_unregister(adap); | 214 | dvb_usb_media_device_unregister(adap); |
215 | err_mc: | ||
207 | dvb_unregister_adapter(&adap->dvb_adap); | 216 | dvb_unregister_adapter(&adap->dvb_adap); |
208 | err: | 217 | err: |
209 | return ret; | 218 | return ret; |
@@ -318,10 +327,16 @@ int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap) | |||
318 | 327 | ||
319 | adap->num_frontends_initialized++; | 328 | adap->num_frontends_initialized++; |
320 | } | 329 | } |
330 | if (ret) | ||
331 | return ret; | ||
321 | 332 | ||
322 | dvb_create_media_graph(&adap->dvb_adap); | 333 | ret = dvb_create_media_graph(&adap->dvb_adap, true); |
334 | if (ret) | ||
335 | return ret; | ||
323 | 336 | ||
324 | return 0; | 337 | ret = dvb_usb_media_device_register(adap); |
338 | |||
339 | return ret; | ||
325 | } | 340 | } |
326 | 341 | ||
327 | int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap) | 342 | int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap) |
diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index c945e4c2fbd4..8abbd3cc8eba 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c | |||
@@ -361,10 +361,11 @@ static void *siano_media_device_register(struct smsusb_device_t *dev, | |||
361 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | 361 | mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); |
362 | mdev->driver_version = LINUX_VERSION_CODE; | 362 | mdev->driver_version = LINUX_VERSION_CODE; |
363 | 363 | ||
364 | media_device_init(mdev); | ||
365 | |||
364 | ret = media_device_register(mdev); | 366 | ret = media_device_register(mdev); |
365 | if (ret) { | 367 | if (ret) { |
366 | pr_err("Couldn't create a media device. Error: %d\n", | 368 | media_device_cleanup(mdev); |
367 | ret); | ||
368 | kfree(mdev); | 369 | kfree(mdev); |
369 | return NULL; | 370 | return NULL; |
370 | } | 371 | } |
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 39abbafad796..4e7148815a78 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c | |||
@@ -1656,6 +1656,7 @@ static void uvc_delete(struct uvc_device *dev) | |||
1656 | #ifdef CONFIG_MEDIA_CONTROLLER | 1656 | #ifdef CONFIG_MEDIA_CONTROLLER |
1657 | if (media_devnode_is_registered(&dev->mdev.devnode)) | 1657 | if (media_devnode_is_registered(&dev->mdev.devnode)) |
1658 | media_device_unregister(&dev->mdev); | 1658 | media_device_unregister(&dev->mdev); |
1659 | media_device_cleanup(&dev->mdev); | ||
1659 | #endif | 1660 | #endif |
1660 | 1661 | ||
1661 | list_for_each_safe(p, n, &dev->chains) { | 1662 | list_for_each_safe(p, n, &dev->chains) { |
@@ -1906,7 +1907,7 @@ static int uvc_probe(struct usb_interface *intf, | |||
1906 | "linux-uvc-devel mailing list.\n"); | 1907 | "linux-uvc-devel mailing list.\n"); |
1907 | } | 1908 | } |
1908 | 1909 | ||
1909 | /* Register the media and V4L2 devices. */ | 1910 | /* Initialize the media device and register the V4L2 device. */ |
1910 | #ifdef CONFIG_MEDIA_CONTROLLER | 1911 | #ifdef CONFIG_MEDIA_CONTROLLER |
1911 | dev->mdev.dev = &intf->dev; | 1912 | dev->mdev.dev = &intf->dev; |
1912 | strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); | 1913 | strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); |
@@ -1916,8 +1917,7 @@ static int uvc_probe(struct usb_interface *intf, | |||
1916 | strcpy(dev->mdev.bus_info, udev->devpath); | 1917 | strcpy(dev->mdev.bus_info, udev->devpath); |
1917 | dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | 1918 | dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); |
1918 | dev->mdev.driver_version = LINUX_VERSION_CODE; | 1919 | dev->mdev.driver_version = LINUX_VERSION_CODE; |
1919 | if (media_device_register(&dev->mdev) < 0) | 1920 | media_device_init(&dev->mdev); |
1920 | goto error; | ||
1921 | 1921 | ||
1922 | dev->vdev.mdev = &dev->mdev; | 1922 | dev->vdev.mdev = &dev->mdev; |
1923 | #endif | 1923 | #endif |
@@ -1936,6 +1936,11 @@ static int uvc_probe(struct usb_interface *intf, | |||
1936 | if (uvc_register_chains(dev) < 0) | 1936 | if (uvc_register_chains(dev) < 0) |
1937 | goto error; | 1937 | goto error; |
1938 | 1938 | ||
1939 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
1940 | /* Register the media device node */ | ||
1941 | if (media_device_register(&dev->mdev) < 0) | ||
1942 | goto error; | ||
1943 | #endif | ||
1939 | /* Save our data pointer in the interface data. */ | 1944 | /* Save our data pointer in the interface data. */ |
1940 | usb_set_intfdata(intf, dev); | 1945 | usb_set_intfdata(intf, dev); |
1941 | 1946 | ||
diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c index dc56a59ecadc..ac386bb547e6 100644 --- a/drivers/media/usb/uvc/uvc_entity.c +++ b/drivers/media/usb/uvc/uvc_entity.c | |||
@@ -19,12 +19,8 @@ | |||
19 | 19 | ||
20 | #include "uvcvideo.h" | 20 | #include "uvcvideo.h" |
21 | 21 | ||
22 | /* ------------------------------------------------------------------------ | 22 | static int uvc_mc_create_links(struct uvc_video_chain *chain, |
23 | * Video subdevices registration and unregistration | 23 | struct uvc_entity *entity) |
24 | */ | ||
25 | |||
26 | static int uvc_mc_register_entity(struct uvc_video_chain *chain, | ||
27 | struct uvc_entity *entity) | ||
28 | { | 24 | { |
29 | const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; | 25 | const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; |
30 | struct media_entity *sink; | 26 | struct media_entity *sink; |
@@ -56,16 +52,13 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, | |||
56 | continue; | 52 | continue; |
57 | 53 | ||
58 | remote_pad = remote->num_pads - 1; | 54 | remote_pad = remote->num_pads - 1; |
59 | ret = media_entity_create_link(source, remote_pad, | 55 | ret = media_create_pad_link(source, remote_pad, |
60 | sink, i, flags); | 56 | sink, i, flags); |
61 | if (ret < 0) | 57 | if (ret < 0) |
62 | return ret; | 58 | return ret; |
63 | } | 59 | } |
64 | 60 | ||
65 | if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) | 61 | return 0; |
66 | return 0; | ||
67 | |||
68 | return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev); | ||
69 | } | 62 | } |
70 | 63 | ||
71 | static struct v4l2_subdev_ops uvc_subdev_ops = { | 64 | static struct v4l2_subdev_ops uvc_subdev_ops = { |
@@ -79,7 +72,8 @@ void uvc_mc_cleanup_entity(struct uvc_entity *entity) | |||
79 | media_entity_cleanup(&entity->vdev->entity); | 72 | media_entity_cleanup(&entity->vdev->entity); |
80 | } | 73 | } |
81 | 74 | ||
82 | static int uvc_mc_init_entity(struct uvc_entity *entity) | 75 | static int uvc_mc_init_entity(struct uvc_video_chain *chain, |
76 | struct uvc_entity *entity) | ||
83 | { | 77 | { |
84 | int ret; | 78 | int ret; |
85 | 79 | ||
@@ -88,11 +82,17 @@ static int uvc_mc_init_entity(struct uvc_entity *entity) | |||
88 | strlcpy(entity->subdev.name, entity->name, | 82 | strlcpy(entity->subdev.name, entity->name, |
89 | sizeof(entity->subdev.name)); | 83 | sizeof(entity->subdev.name)); |
90 | 84 | ||
91 | ret = media_entity_init(&entity->subdev.entity, | 85 | ret = media_entity_pads_init(&entity->subdev.entity, |
92 | entity->num_pads, entity->pads, 0); | 86 | entity->num_pads, entity->pads); |
87 | |||
88 | if (ret < 0) | ||
89 | return ret; | ||
90 | |||
91 | ret = v4l2_device_register_subdev(&chain->dev->vdev, | ||
92 | &entity->subdev); | ||
93 | } else if (entity->vdev != NULL) { | 93 | } else if (entity->vdev != NULL) { |
94 | ret = media_entity_init(&entity->vdev->entity, | 94 | ret = media_entity_pads_init(&entity->vdev->entity, |
95 | entity->num_pads, entity->pads, 0); | 95 | entity->num_pads, entity->pads); |
96 | if (entity->flags & UVC_ENTITY_FLAG_DEFAULT) | 96 | if (entity->flags & UVC_ENTITY_FLAG_DEFAULT) |
97 | entity->vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT; | 97 | entity->vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT; |
98 | } else | 98 | } else |
@@ -107,7 +107,7 @@ int uvc_mc_register_entities(struct uvc_video_chain *chain) | |||
107 | int ret; | 107 | int ret; |
108 | 108 | ||
109 | list_for_each_entry(entity, &chain->entities, chain) { | 109 | list_for_each_entry(entity, &chain->entities, chain) { |
110 | ret = uvc_mc_init_entity(entity); | 110 | ret = uvc_mc_init_entity(chain, entity); |
111 | if (ret < 0) { | 111 | if (ret < 0) { |
112 | uvc_printk(KERN_INFO, "Failed to initialize entity for " | 112 | uvc_printk(KERN_INFO, "Failed to initialize entity for " |
113 | "entity %u\n", entity->id); | 113 | "entity %u\n", entity->id); |
@@ -116,9 +116,9 @@ int uvc_mc_register_entities(struct uvc_video_chain *chain) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | list_for_each_entry(entity, &chain->entities, chain) { | 118 | list_for_each_entry(entity, &chain->entities, chain) { |
119 | ret = uvc_mc_register_entity(chain, entity); | 119 | ret = uvc_mc_create_links(chain, entity); |
120 | if (ret < 0) { | 120 | if (ret < 0) { |
121 | uvc_printk(KERN_INFO, "Failed to register entity for " | 121 | uvc_printk(KERN_INFO, "Failed to create links for " |
122 | "entity %u\n", entity->id); | 122 | "entity %u\n", entity->id); |
123 | return ret; | 123 | return ret; |
124 | } | 124 | } |
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 581e21ad6801..76496fd282aa 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c | |||
@@ -134,8 +134,9 @@ struct tuner { | |||
134 | unsigned int type; /* chip type id */ | 134 | unsigned int type; /* chip type id */ |
135 | void *config; | 135 | void *config; |
136 | const char *name; | 136 | const char *name; |
137 | |||
137 | #if defined(CONFIG_MEDIA_CONTROLLER) | 138 | #if defined(CONFIG_MEDIA_CONTROLLER) |
138 | struct media_pad pad; | 139 | struct media_pad pad[TUNER_NUM_PADS]; |
139 | #endif | 140 | #endif |
140 | }; | 141 | }; |
141 | 142 | ||
@@ -695,11 +696,12 @@ static int tuner_probe(struct i2c_client *client, | |||
695 | /* Should be just before return */ | 696 | /* Should be just before return */ |
696 | register_client: | 697 | register_client: |
697 | #if defined(CONFIG_MEDIA_CONTROLLER) | 698 | #if defined(CONFIG_MEDIA_CONTROLLER) |
698 | t->pad.flags = MEDIA_PAD_FL_SOURCE; | 699 | t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; |
699 | t->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_TUNER; | 700 | t->pad[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; |
701 | t->sd.entity.function = MEDIA_ENT_F_TUNER; | ||
700 | t->sd.entity.name = t->name; | 702 | t->sd.entity.name = t->name; |
701 | 703 | ||
702 | ret = media_entity_init(&t->sd.entity, 1, &t->pad, 0); | 704 | ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, &t->pad[0]); |
703 | if (ret < 0) { | 705 | if (ret < 0) { |
704 | tuner_err("failed to initialize media entity!\n"); | 706 | tuner_err("failed to initialize media entity!\n"); |
705 | kfree(t); | 707 | kfree(t); |
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 6b1eaeddbdb3..d8e5994cccf1 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c | |||
@@ -194,9 +194,12 @@ static void v4l2_device_release(struct device *cd) | |||
194 | mutex_unlock(&videodev_lock); | 194 | mutex_unlock(&videodev_lock); |
195 | 195 | ||
196 | #if defined(CONFIG_MEDIA_CONTROLLER) | 196 | #if defined(CONFIG_MEDIA_CONTROLLER) |
197 | if (v4l2_dev->mdev && | 197 | if (v4l2_dev->mdev) { |
198 | vdev->vfl_type != VFL_TYPE_SUBDEV) | 198 | /* Remove interfaces and interface links */ |
199 | media_device_unregister_entity(&vdev->entity); | 199 | media_devnode_remove(vdev->intf_devnode); |
200 | if (vdev->entity.function != MEDIA_ENT_F_UNKNOWN) | ||
201 | media_device_unregister_entity(&vdev->entity); | ||
202 | } | ||
200 | #endif | 203 | #endif |
201 | 204 | ||
202 | /* Do not call v4l2_device_put if there is no release callback set. | 205 | /* Do not call v4l2_device_put if there is no release callback set. |
@@ -723,6 +726,91 @@ static void determine_valid_ioctls(struct video_device *vdev) | |||
723 | BASE_VIDIOC_PRIVATE); | 726 | BASE_VIDIOC_PRIVATE); |
724 | } | 727 | } |
725 | 728 | ||
729 | static int video_register_media_controller(struct video_device *vdev, int type) | ||
730 | { | ||
731 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
732 | u32 intf_type; | ||
733 | int ret; | ||
734 | |||
735 | if (!vdev->v4l2_dev->mdev) | ||
736 | return 0; | ||
737 | |||
738 | vdev->entity.function = MEDIA_ENT_F_UNKNOWN; | ||
739 | |||
740 | switch (type) { | ||
741 | case VFL_TYPE_GRABBER: | ||
742 | intf_type = MEDIA_INTF_T_V4L_VIDEO; | ||
743 | vdev->entity.function = MEDIA_ENT_F_IO_V4L; | ||
744 | break; | ||
745 | case VFL_TYPE_VBI: | ||
746 | intf_type = MEDIA_INTF_T_V4L_VBI; | ||
747 | vdev->entity.function = MEDIA_ENT_F_IO_VBI; | ||
748 | break; | ||
749 | case VFL_TYPE_SDR: | ||
750 | intf_type = MEDIA_INTF_T_V4L_SWRADIO; | ||
751 | vdev->entity.function = MEDIA_ENT_F_IO_SWRADIO; | ||
752 | break; | ||
753 | case VFL_TYPE_RADIO: | ||
754 | intf_type = MEDIA_INTF_T_V4L_RADIO; | ||
755 | /* | ||
756 | * Radio doesn't have an entity at the V4L2 side to represent | ||
757 | * radio input or output. Instead, the audio input/output goes | ||
758 | * via either physical wires or ALSA. | ||
759 | */ | ||
760 | break; | ||
761 | case VFL_TYPE_SUBDEV: | ||
762 | intf_type = MEDIA_INTF_T_V4L_SUBDEV; | ||
763 | /* Entity will be created via v4l2_device_register_subdev() */ | ||
764 | break; | ||
765 | default: | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | if (vdev->entity.function != MEDIA_ENT_F_UNKNOWN) { | ||
770 | vdev->entity.name = vdev->name; | ||
771 | |||
772 | /* Needed just for backward compatibility with legacy MC API */ | ||
773 | vdev->entity.info.dev.major = VIDEO_MAJOR; | ||
774 | vdev->entity.info.dev.minor = vdev->minor; | ||
775 | |||
776 | ret = media_device_register_entity(vdev->v4l2_dev->mdev, | ||
777 | &vdev->entity); | ||
778 | if (ret < 0) { | ||
779 | printk(KERN_WARNING | ||
780 | "%s: media_device_register_entity failed\n", | ||
781 | __func__); | ||
782 | return ret; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev, | ||
787 | intf_type, | ||
788 | 0, VIDEO_MAJOR, | ||
789 | vdev->minor); | ||
790 | if (!vdev->intf_devnode) { | ||
791 | media_device_unregister_entity(&vdev->entity); | ||
792 | return -ENOMEM; | ||
793 | } | ||
794 | |||
795 | if (vdev->entity.function != MEDIA_ENT_F_UNKNOWN) { | ||
796 | struct media_link *link; | ||
797 | |||
798 | link = media_create_intf_link(&vdev->entity, | ||
799 | &vdev->intf_devnode->intf, | ||
800 | MEDIA_LNK_FL_ENABLED); | ||
801 | if (!link) { | ||
802 | media_devnode_remove(vdev->intf_devnode); | ||
803 | media_device_unregister_entity(&vdev->entity); | ||
804 | return -ENOMEM; | ||
805 | } | ||
806 | } | ||
807 | |||
808 | /* FIXME: how to create the other interface links? */ | ||
809 | |||
810 | #endif | ||
811 | return 0; | ||
812 | } | ||
813 | |||
726 | /** | 814 | /** |
727 | * __video_register_device - register video4linux devices | 815 | * __video_register_device - register video4linux devices |
728 | * @vdev: video device structure we want to register | 816 | * @vdev: video device structure we want to register |
@@ -918,22 +1006,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr, | |||
918 | /* Increase v4l2_device refcount */ | 1006 | /* Increase v4l2_device refcount */ |
919 | v4l2_device_get(vdev->v4l2_dev); | 1007 | v4l2_device_get(vdev->v4l2_dev); |
920 | 1008 | ||
921 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
922 | /* Part 5: Register the entity. */ | 1009 | /* Part 5: Register the entity. */ |
923 | if (vdev->v4l2_dev->mdev && | 1010 | ret = video_register_media_controller(vdev, type); |
924 | vdev->vfl_type != VFL_TYPE_SUBDEV) { | 1011 | |
925 | vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; | ||
926 | vdev->entity.name = vdev->name; | ||
927 | vdev->entity.info.dev.major = VIDEO_MAJOR; | ||
928 | vdev->entity.info.dev.minor = vdev->minor; | ||
929 | ret = media_device_register_entity(vdev->v4l2_dev->mdev, | ||
930 | &vdev->entity); | ||
931 | if (ret < 0) | ||
932 | printk(KERN_WARNING | ||
933 | "%s: media_device_register_entity failed\n", | ||
934 | __func__); | ||
935 | } | ||
936 | #endif | ||
937 | /* Part 6: Activate this minor. The char device can now be used. */ | 1012 | /* Part 6: Activate this minor. The char device can now be used. */ |
938 | set_bit(V4L2_FL_REGISTERED, &vdev->flags); | 1013 | set_bit(V4L2_FL_REGISTERED, &vdev->flags); |
939 | 1014 | ||
diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 7129e438f29e..06fa5f1b2cff 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c | |||
@@ -180,26 +180,26 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, | |||
180 | return -ENODEV; | 180 | return -ENODEV; |
181 | 181 | ||
182 | sd->v4l2_dev = v4l2_dev; | 182 | sd->v4l2_dev = v4l2_dev; |
183 | if (sd->internal_ops && sd->internal_ops->registered) { | ||
184 | err = sd->internal_ops->registered(sd); | ||
185 | if (err) | ||
186 | goto error_module; | ||
187 | } | ||
188 | |||
189 | /* This just returns 0 if either of the two args is NULL */ | 183 | /* This just returns 0 if either of the two args is NULL */ |
190 | err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL); | 184 | err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL); |
191 | if (err) | 185 | if (err) |
192 | goto error_unregister; | 186 | goto error_module; |
193 | 187 | ||
194 | #if defined(CONFIG_MEDIA_CONTROLLER) | 188 | #if defined(CONFIG_MEDIA_CONTROLLER) |
195 | /* Register the entity. */ | 189 | /* Register the entity. */ |
196 | if (v4l2_dev->mdev) { | 190 | if (v4l2_dev->mdev) { |
197 | err = media_device_register_entity(v4l2_dev->mdev, entity); | 191 | err = media_device_register_entity(v4l2_dev->mdev, entity); |
198 | if (err < 0) | 192 | if (err < 0) |
199 | goto error_unregister; | 193 | goto error_module; |
200 | } | 194 | } |
201 | #endif | 195 | #endif |
202 | 196 | ||
197 | if (sd->internal_ops && sd->internal_ops->registered) { | ||
198 | err = sd->internal_ops->registered(sd); | ||
199 | if (err) | ||
200 | goto error_unregister; | ||
201 | } | ||
202 | |||
203 | spin_lock(&v4l2_dev->lock); | 203 | spin_lock(&v4l2_dev->lock); |
204 | list_add_tail(&sd->list, &v4l2_dev->subdevs); | 204 | list_add_tail(&sd->list, &v4l2_dev->subdevs); |
205 | spin_unlock(&v4l2_dev->lock); | 205 | spin_unlock(&v4l2_dev->lock); |
@@ -207,8 +207,9 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, | |||
207 | return 0; | 207 | return 0; |
208 | 208 | ||
209 | error_unregister: | 209 | error_unregister: |
210 | if (sd->internal_ops && sd->internal_ops->unregistered) | 210 | #if defined(CONFIG_MEDIA_CONTROLLER) |
211 | sd->internal_ops->unregistered(sd); | 211 | media_device_unregister_entity(entity); |
212 | #endif | ||
212 | error_module: | 213 | error_module: |
213 | if (!sd->owner_v4l2_dev) | 214 | if (!sd->owner_v4l2_dev) |
214 | module_put(sd->owner); | 215 | module_put(sd->owner); |
@@ -258,6 +259,19 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) | |||
258 | #if defined(CONFIG_MEDIA_CONTROLLER) | 259 | #if defined(CONFIG_MEDIA_CONTROLLER) |
259 | sd->entity.info.dev.major = VIDEO_MAJOR; | 260 | sd->entity.info.dev.major = VIDEO_MAJOR; |
260 | sd->entity.info.dev.minor = vdev->minor; | 261 | sd->entity.info.dev.minor = vdev->minor; |
262 | |||
263 | /* Interface is created by __video_register_device() */ | ||
264 | if (vdev->v4l2_dev->mdev) { | ||
265 | struct media_link *link; | ||
266 | |||
267 | link = media_create_intf_link(&sd->entity, | ||
268 | &vdev->intf_devnode->intf, | ||
269 | MEDIA_LNK_FL_ENABLED); | ||
270 | if (!link) { | ||
271 | err = -ENOMEM; | ||
272 | goto clean_up; | ||
273 | } | ||
274 | } | ||
261 | #endif | 275 | #endif |
262 | sd->devnode = vdev; | 276 | sd->devnode = vdev; |
263 | } | 277 | } |
@@ -294,7 +308,10 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) | |||
294 | 308 | ||
295 | #if defined(CONFIG_MEDIA_CONTROLLER) | 309 | #if defined(CONFIG_MEDIA_CONTROLLER) |
296 | if (v4l2_dev->mdev) { | 310 | if (v4l2_dev->mdev) { |
297 | media_entity_remove_links(&sd->entity); | 311 | /* |
312 | * No need to explicitly remove links, as both pads and | ||
313 | * links are removed by the function below, in the right order | ||
314 | */ | ||
298 | media_device_unregister_entity(&sd->entity); | 315 | media_device_unregister_entity(&sd->entity); |
299 | } | 316 | } |
300 | #endif | 317 | #endif |
diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c index 5d673357f75f..fc5ff8b215f9 100644 --- a/drivers/media/v4l2-core/v4l2-flash-led-class.c +++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c | |||
@@ -651,11 +651,11 @@ struct v4l2_flash *v4l2_flash_init( | |||
651 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 651 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
652 | strlcpy(sd->name, config->dev_name, sizeof(sd->name)); | 652 | strlcpy(sd->name, config->dev_name, sizeof(sd->name)); |
653 | 653 | ||
654 | ret = media_entity_init(&sd->entity, 0, NULL, 0); | 654 | ret = media_entity_pads_init(&sd->entity, 0, NULL); |
655 | if (ret < 0) | 655 | if (ret < 0) |
656 | return ERR_PTR(ret); | 656 | return ERR_PTR(ret); |
657 | 657 | ||
658 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH; | 658 | sd->entity.function = MEDIA_ENT_F_FLASH; |
659 | 659 | ||
660 | ret = v4l2_flash_init_controls(v4l2_flash, config); | 660 | ret = v4l2_flash_init_controls(v4l2_flash, config); |
661 | if (ret < 0) | 661 | if (ret < 0) |
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 83615b8fb46a..d63083803144 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c | |||
@@ -526,7 +526,7 @@ static int | |||
526 | v4l2_subdev_link_validate_get_format(struct media_pad *pad, | 526 | v4l2_subdev_link_validate_get_format(struct media_pad *pad, |
527 | struct v4l2_subdev_format *fmt) | 527 | struct v4l2_subdev_format *fmt) |
528 | { | 528 | { |
529 | if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) { | 529 | if (is_media_entity_v4l2_subdev(pad->entity)) { |
530 | struct v4l2_subdev *sd = | 530 | struct v4l2_subdev *sd = |
531 | media_entity_to_v4l2_subdev(pad->entity); | 531 | media_entity_to_v4l2_subdev(pad->entity); |
532 | 532 | ||
@@ -535,9 +535,9 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad, | |||
535 | return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt); | 535 | return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt); |
536 | } | 536 | } |
537 | 537 | ||
538 | WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L, | 538 | WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L, |
539 | "Driver bug! Wrong media entity type 0x%08x, entity %s\n", | 539 | "Driver bug! Wrong media entity type 0x%08x, entity %s\n", |
540 | pad->entity->type, pad->entity->name); | 540 | pad->entity->function, pad->entity->name); |
541 | 541 | ||
542 | return -EINVAL; | 542 | return -EINVAL; |
543 | } | 543 | } |
@@ -584,7 +584,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) | |||
584 | sd->host_priv = NULL; | 584 | sd->host_priv = NULL; |
585 | #if defined(CONFIG_MEDIA_CONTROLLER) | 585 | #if defined(CONFIG_MEDIA_CONTROLLER) |
586 | sd->entity.name = sd->name; | 586 | sd->entity.name = sd->name; |
587 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV; | 587 | sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; |
588 | #endif | 588 | #endif |
589 | } | 589 | } |
590 | EXPORT_SYMBOL(v4l2_subdev_init); | 590 | EXPORT_SYMBOL(v4l2_subdev_init); |
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index c492914768ea..ac78ed2f8bcc 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c | |||
@@ -1712,8 +1712,11 @@ ipipe_link_setup(struct media_entity *entity, const struct media_pad *local, | |||
1712 | struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); | 1712 | struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); |
1713 | u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; | 1713 | u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; |
1714 | 1714 | ||
1715 | switch (local->index | media_entity_type(remote->entity)) { | 1715 | if (!is_media_entity_v4l2_subdev(remote->entity)) |
1716 | case IPIPE_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 1716 | return -EINVAL; |
1717 | |||
1718 | switch (local->index) { | ||
1719 | case IPIPE_PAD_SINK: | ||
1717 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1720 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1718 | ipipe->input = IPIPE_INPUT_NONE; | 1721 | ipipe->input = IPIPE_INPUT_NONE; |
1719 | break; | 1722 | break; |
@@ -1726,7 +1729,7 @@ ipipe_link_setup(struct media_entity *entity, const struct media_pad *local, | |||
1726 | ipipe->input = IPIPE_INPUT_CCDC; | 1729 | ipipe->input = IPIPE_INPUT_CCDC; |
1727 | break; | 1730 | break; |
1728 | 1731 | ||
1729 | case IPIPE_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: | 1732 | case IPIPE_PAD_SOURCE: |
1730 | /* out to RESIZER */ | 1733 | /* out to RESIZER */ |
1731 | if (flags & MEDIA_LNK_FL_ENABLED) | 1734 | if (flags & MEDIA_LNK_FL_ENABLED) |
1732 | ipipe->output = IPIPE_OUTPUT_RESIZER; | 1735 | ipipe->output = IPIPE_OUTPUT_RESIZER; |
@@ -1840,7 +1843,7 @@ vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, struct platform_device *pdev) | |||
1840 | v4l2_ctrl_handler_setup(&ipipe->ctrls); | 1843 | v4l2_ctrl_handler_setup(&ipipe->ctrls); |
1841 | sd->ctrl_handler = &ipipe->ctrls; | 1844 | sd->ctrl_handler = &ipipe->ctrls; |
1842 | 1845 | ||
1843 | return media_entity_init(me, IPIPE_PADS_NUM, pads, 0); | 1846 | return media_entity_pads_init(me, IPIPE_PADS_NUM, pads); |
1844 | } | 1847 | } |
1845 | 1848 | ||
1846 | /* | 1849 | /* |
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c index 8b230541b1d1..633d6456fdce 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c | |||
@@ -885,9 +885,14 @@ ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local, | |||
885 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 885 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
886 | struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); | 886 | struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); |
887 | struct vpfe_device *vpfe = to_vpfe_device(ipipeif); | 887 | struct vpfe_device *vpfe = to_vpfe_device(ipipeif); |
888 | unsigned int index = local->index; | ||
888 | 889 | ||
889 | switch (local->index | media_entity_type(remote->entity)) { | 890 | /* FIXME: this is actually a hack! */ |
890 | case IPIPEIF_PAD_SINK | MEDIA_ENT_T_DEVNODE: | 891 | if (is_media_entity_v4l2_subdev(remote->entity)) |
892 | index |= 2 << 16; | ||
893 | |||
894 | switch (index) { | ||
895 | case IPIPEIF_PAD_SINK: | ||
891 | /* Single shot mode */ | 896 | /* Single shot mode */ |
892 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 897 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
893 | ipipeif->input = IPIPEIF_INPUT_NONE; | 898 | ipipeif->input = IPIPEIF_INPUT_NONE; |
@@ -896,7 +901,7 @@ ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local, | |||
896 | ipipeif->input = IPIPEIF_INPUT_MEMORY; | 901 | ipipeif->input = IPIPEIF_INPUT_MEMORY; |
897 | break; | 902 | break; |
898 | 903 | ||
899 | case IPIPEIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 904 | case IPIPEIF_PAD_SINK | 2 << 16: |
900 | /* read from isif */ | 905 | /* read from isif */ |
901 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 906 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
902 | ipipeif->input = IPIPEIF_INPUT_NONE; | 907 | ipipeif->input = IPIPEIF_INPUT_NONE; |
@@ -908,7 +913,7 @@ ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local, | |||
908 | ipipeif->input = IPIPEIF_INPUT_ISIF; | 913 | ipipeif->input = IPIPEIF_INPUT_ISIF; |
909 | break; | 914 | break; |
910 | 915 | ||
911 | case IPIPEIF_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: | 916 | case IPIPEIF_PAD_SOURCE | 2 << 16: |
912 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 917 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
913 | ipipeif->output = IPIPEIF_OUTPUT_NONE; | 918 | ipipeif->output = IPIPEIF_OUTPUT_NONE; |
914 | break; | 919 | break; |
@@ -971,7 +976,7 @@ vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif, | |||
971 | ipipeif->video_in.vpfe_dev = vpfe_dev; | 976 | ipipeif->video_in.vpfe_dev = vpfe_dev; |
972 | 977 | ||
973 | flags = 0; | 978 | flags = 0; |
974 | ret = media_entity_create_link(&ipipeif->video_in.video_dev.entity, 0, | 979 | ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0, |
975 | &ipipeif->subdev.entity, 0, flags); | 980 | &ipipeif->subdev.entity, 0, flags); |
976 | if (ret < 0) | 981 | if (ret < 0) |
977 | goto fail; | 982 | goto fail; |
@@ -1026,7 +1031,7 @@ int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif, | |||
1026 | ipipeif->output = IPIPEIF_OUTPUT_NONE; | 1031 | ipipeif->output = IPIPEIF_OUTPUT_NONE; |
1027 | me->ops = &ipipeif_media_ops; | 1032 | me->ops = &ipipeif_media_ops; |
1028 | 1033 | ||
1029 | ret = media_entity_init(me, IPIPEIF_NUM_PADS, pads, 0); | 1034 | ret = media_entity_pads_init(me, IPIPEIF_NUM_PADS, pads); |
1030 | if (ret) | 1035 | if (ret) |
1031 | goto fail; | 1036 | goto fail; |
1032 | 1037 | ||
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index 80907b464412..99057892d88d 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c | |||
@@ -1707,9 +1707,14 @@ isif_link_setup(struct media_entity *entity, const struct media_pad *local, | |||
1707 | { | 1707 | { |
1708 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 1708 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
1709 | struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); | 1709 | struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); |
1710 | unsigned int index = local->index; | ||
1710 | 1711 | ||
1711 | switch (local->index | media_entity_type(remote->entity)) { | 1712 | /* FIXME: this is actually a hack! */ |
1712 | case ISIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 1713 | if (is_media_entity_v4l2_subdev(remote->entity)) |
1714 | index |= 2 << 16; | ||
1715 | |||
1716 | switch (index) { | ||
1717 | case ISIF_PAD_SINK | 2 << 16: | ||
1713 | /* read from decoder/sensor */ | 1718 | /* read from decoder/sensor */ |
1714 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1719 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1715 | isif->input = ISIF_INPUT_NONE; | 1720 | isif->input = ISIF_INPUT_NONE; |
@@ -1720,7 +1725,7 @@ isif_link_setup(struct media_entity *entity, const struct media_pad *local, | |||
1720 | isif->input = ISIF_INPUT_PARALLEL; | 1725 | isif->input = ISIF_INPUT_PARALLEL; |
1721 | break; | 1726 | break; |
1722 | 1727 | ||
1723 | case ISIF_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: | 1728 | case ISIF_PAD_SOURCE: |
1724 | /* write to memory */ | 1729 | /* write to memory */ |
1725 | if (flags & MEDIA_LNK_FL_ENABLED) | 1730 | if (flags & MEDIA_LNK_FL_ENABLED) |
1726 | isif->output = ISIF_OUTPUT_MEMORY; | 1731 | isif->output = ISIF_OUTPUT_MEMORY; |
@@ -1728,7 +1733,7 @@ isif_link_setup(struct media_entity *entity, const struct media_pad *local, | |||
1728 | isif->output = ISIF_OUTPUT_NONE; | 1733 | isif->output = ISIF_OUTPUT_NONE; |
1729 | break; | 1734 | break; |
1730 | 1735 | ||
1731 | case ISIF_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: | 1736 | case ISIF_PAD_SOURCE | 2 << 16: |
1732 | if (flags & MEDIA_LNK_FL_ENABLED) | 1737 | if (flags & MEDIA_LNK_FL_ENABLED) |
1733 | isif->output = ISIF_OUTPUT_IPIPEIF; | 1738 | isif->output = ISIF_OUTPUT_IPIPEIF; |
1734 | else | 1739 | else |
@@ -1817,7 +1822,7 @@ int vpfe_isif_register_entities(struct vpfe_isif_device *isif, | |||
1817 | isif->video_out.vpfe_dev = vpfe_dev; | 1822 | isif->video_out.vpfe_dev = vpfe_dev; |
1818 | flags = 0; | 1823 | flags = 0; |
1819 | /* connect isif to video node */ | 1824 | /* connect isif to video node */ |
1820 | ret = media_entity_create_link(&isif->subdev.entity, 1, | 1825 | ret = media_create_pad_link(&isif->subdev.entity, 1, |
1821 | &isif->video_out.video_dev.entity, | 1826 | &isif->video_out.video_dev.entity, |
1822 | 0, flags); | 1827 | 0, flags); |
1823 | if (ret < 0) | 1828 | if (ret < 0) |
@@ -2052,7 +2057,7 @@ int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev) | |||
2052 | isif->input = ISIF_INPUT_NONE; | 2057 | isif->input = ISIF_INPUT_NONE; |
2053 | isif->output = ISIF_OUTPUT_NONE; | 2058 | isif->output = ISIF_OUTPUT_NONE; |
2054 | me->ops = &isif_media_ops; | 2059 | me->ops = &isif_media_ops; |
2055 | status = media_entity_init(me, ISIF_PADS_NUM, pads, 0); | 2060 | status = media_entity_pads_init(me, ISIF_PADS_NUM, pads); |
2056 | if (status) | 2061 | if (status) |
2057 | goto isif_fail; | 2062 | goto isif_fail; |
2058 | isif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 2063 | isif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index d892fee3f52f..a91395ce91e1 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c | |||
@@ -1648,10 +1648,15 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1648 | struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); | 1648 | struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); |
1649 | u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output; | 1649 | u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output; |
1650 | u16 ipipe_source = vpfe_dev->vpfe_ipipe.output; | 1650 | u16 ipipe_source = vpfe_dev->vpfe_ipipe.output; |
1651 | unsigned int index = local->index; | ||
1652 | |||
1653 | /* FIXME: this is actually a hack! */ | ||
1654 | if (is_media_entity_v4l2_subdev(remote->entity)) | ||
1655 | index |= 2 << 16; | ||
1651 | 1656 | ||
1652 | if (&resizer->crop_resizer.subdev == sd) { | 1657 | if (&resizer->crop_resizer.subdev == sd) { |
1653 | switch (local->index | media_entity_type(remote->entity)) { | 1658 | switch (index) { |
1654 | case RESIZER_CROP_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 1659 | case RESIZER_CROP_PAD_SINK | 2 << 16: |
1655 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1660 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1656 | resizer->crop_resizer.input = | 1661 | resizer->crop_resizer.input = |
1657 | RESIZER_CROP_INPUT_NONE; | 1662 | RESIZER_CROP_INPUT_NONE; |
@@ -1671,7 +1676,7 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1671 | return -EINVAL; | 1676 | return -EINVAL; |
1672 | break; | 1677 | break; |
1673 | 1678 | ||
1674 | case RESIZER_CROP_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: | 1679 | case RESIZER_CROP_PAD_SOURCE | 2 << 16: |
1675 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1680 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1676 | resizer->crop_resizer.output = | 1681 | resizer->crop_resizer.output = |
1677 | RESIZER_CROP_OUTPUT_NONE; | 1682 | RESIZER_CROP_OUTPUT_NONE; |
@@ -1683,7 +1688,7 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1683 | resizer->crop_resizer.output = RESIZER_A; | 1688 | resizer->crop_resizer.output = RESIZER_A; |
1684 | break; | 1689 | break; |
1685 | 1690 | ||
1686 | case RESIZER_CROP_PAD_SOURCE2 | MEDIA_ENT_T_V4L2_SUBDEV: | 1691 | case RESIZER_CROP_PAD_SOURCE2 | 2 << 16: |
1687 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1692 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1688 | resizer->crop_resizer.output2 = | 1693 | resizer->crop_resizer.output2 = |
1689 | RESIZER_CROP_OUTPUT_NONE; | 1694 | RESIZER_CROP_OUTPUT_NONE; |
@@ -1699,8 +1704,8 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1699 | return -EINVAL; | 1704 | return -EINVAL; |
1700 | } | 1705 | } |
1701 | } else if (&resizer->resizer_a.subdev == sd) { | 1706 | } else if (&resizer->resizer_a.subdev == sd) { |
1702 | switch (local->index | media_entity_type(remote->entity)) { | 1707 | switch (index) { |
1703 | case RESIZER_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 1708 | case RESIZER_PAD_SINK | 2 << 16: |
1704 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1709 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1705 | resizer->resizer_a.input = RESIZER_INPUT_NONE; | 1710 | resizer->resizer_a.input = RESIZER_INPUT_NONE; |
1706 | break; | 1711 | break; |
@@ -1710,7 +1715,7 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1710 | resizer->resizer_a.input = RESIZER_INPUT_CROP_RESIZER; | 1715 | resizer->resizer_a.input = RESIZER_INPUT_CROP_RESIZER; |
1711 | break; | 1716 | break; |
1712 | 1717 | ||
1713 | case RESIZER_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: | 1718 | case RESIZER_PAD_SOURCE: |
1714 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1719 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1715 | resizer->resizer_a.output = RESIZER_OUTPUT_NONE; | 1720 | resizer->resizer_a.output = RESIZER_OUTPUT_NONE; |
1716 | break; | 1721 | break; |
@@ -1724,8 +1729,8 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1724 | return -EINVAL; | 1729 | return -EINVAL; |
1725 | } | 1730 | } |
1726 | } else if (&resizer->resizer_b.subdev == sd) { | 1731 | } else if (&resizer->resizer_b.subdev == sd) { |
1727 | switch (local->index | media_entity_type(remote->entity)) { | 1732 | switch (index) { |
1728 | case RESIZER_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 1733 | case RESIZER_PAD_SINK | 2 << 16: |
1729 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1734 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1730 | resizer->resizer_b.input = RESIZER_INPUT_NONE; | 1735 | resizer->resizer_b.input = RESIZER_INPUT_NONE; |
1731 | break; | 1736 | break; |
@@ -1735,7 +1740,7 @@ static int resizer_link_setup(struct media_entity *entity, | |||
1735 | resizer->resizer_b.input = RESIZER_INPUT_CROP_RESIZER; | 1740 | resizer->resizer_b.input = RESIZER_INPUT_CROP_RESIZER; |
1736 | break; | 1741 | break; |
1737 | 1742 | ||
1738 | case RESIZER_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: | 1743 | case RESIZER_PAD_SOURCE: |
1739 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 1744 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
1740 | resizer->resizer_b.output = RESIZER_OUTPUT_NONE; | 1745 | resizer->resizer_b.output = RESIZER_OUTPUT_NONE; |
1741 | break; | 1746 | break; |
@@ -1826,27 +1831,27 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer, | |||
1826 | resizer->resizer_b.video_out.vpfe_dev = vpfe_dev; | 1831 | resizer->resizer_b.video_out.vpfe_dev = vpfe_dev; |
1827 | 1832 | ||
1828 | /* create link between Resizer Crop----> Resizer A*/ | 1833 | /* create link between Resizer Crop----> Resizer A*/ |
1829 | ret = media_entity_create_link(&resizer->crop_resizer.subdev.entity, 1, | 1834 | ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1, |
1830 | &resizer->resizer_a.subdev.entity, | 1835 | &resizer->resizer_a.subdev.entity, |
1831 | 0, flags); | 1836 | 0, flags); |
1832 | if (ret < 0) | 1837 | if (ret < 0) |
1833 | goto out_create_link; | 1838 | goto out_create_link; |
1834 | 1839 | ||
1835 | /* create link between Resizer Crop----> Resizer B*/ | 1840 | /* create link between Resizer Crop----> Resizer B*/ |
1836 | ret = media_entity_create_link(&resizer->crop_resizer.subdev.entity, 2, | 1841 | ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2, |
1837 | &resizer->resizer_b.subdev.entity, | 1842 | &resizer->resizer_b.subdev.entity, |
1838 | 0, flags); | 1843 | 0, flags); |
1839 | if (ret < 0) | 1844 | if (ret < 0) |
1840 | goto out_create_link; | 1845 | goto out_create_link; |
1841 | 1846 | ||
1842 | /* create link between Resizer A ----> video out */ | 1847 | /* create link between Resizer A ----> video out */ |
1843 | ret = media_entity_create_link(&resizer->resizer_a.subdev.entity, 1, | 1848 | ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1, |
1844 | &resizer->resizer_a.video_out.video_dev.entity, 0, flags); | 1849 | &resizer->resizer_a.video_out.video_dev.entity, 0, flags); |
1845 | if (ret < 0) | 1850 | if (ret < 0) |
1846 | goto out_create_link; | 1851 | goto out_create_link; |
1847 | 1852 | ||
1848 | /* create link between Resizer B ----> video out */ | 1853 | /* create link between Resizer B ----> video out */ |
1849 | ret = media_entity_create_link(&resizer->resizer_b.subdev.entity, 1, | 1854 | ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1, |
1850 | &resizer->resizer_b.video_out.video_dev.entity, 0, flags); | 1855 | &resizer->resizer_b.video_out.video_dev.entity, 0, flags); |
1851 | if (ret < 0) | 1856 | if (ret < 0) |
1852 | goto out_create_link; | 1857 | goto out_create_link; |
@@ -1910,7 +1915,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, | |||
1910 | vpfe_rsz->crop_resizer.output2 = RESIZER_CROP_OUTPUT_NONE; | 1915 | vpfe_rsz->crop_resizer.output2 = RESIZER_CROP_OUTPUT_NONE; |
1911 | vpfe_rsz->crop_resizer.rsz_device = vpfe_rsz; | 1916 | vpfe_rsz->crop_resizer.rsz_device = vpfe_rsz; |
1912 | me->ops = &resizer_media_ops; | 1917 | me->ops = &resizer_media_ops; |
1913 | ret = media_entity_init(me, RESIZER_CROP_PADS_NUM, pads, 0); | 1918 | ret = media_entity_pads_init(me, RESIZER_CROP_PADS_NUM, pads); |
1914 | if (ret) | 1919 | if (ret) |
1915 | return ret; | 1920 | return ret; |
1916 | 1921 | ||
@@ -1932,7 +1937,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, | |||
1932 | vpfe_rsz->resizer_a.output = RESIZER_OUTPUT_NONE; | 1937 | vpfe_rsz->resizer_a.output = RESIZER_OUTPUT_NONE; |
1933 | vpfe_rsz->resizer_a.rsz_device = vpfe_rsz; | 1938 | vpfe_rsz->resizer_a.rsz_device = vpfe_rsz; |
1934 | me->ops = &resizer_media_ops; | 1939 | me->ops = &resizer_media_ops; |
1935 | ret = media_entity_init(me, RESIZER_PADS_NUM, pads, 0); | 1940 | ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); |
1936 | if (ret) | 1941 | if (ret) |
1937 | return ret; | 1942 | return ret; |
1938 | 1943 | ||
@@ -1954,7 +1959,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, | |||
1954 | vpfe_rsz->resizer_b.output = RESIZER_OUTPUT_NONE; | 1959 | vpfe_rsz->resizer_b.output = RESIZER_OUTPUT_NONE; |
1955 | vpfe_rsz->resizer_b.rsz_device = vpfe_rsz; | 1960 | vpfe_rsz->resizer_b.rsz_device = vpfe_rsz; |
1956 | me->ops = &resizer_media_ops; | 1961 | me->ops = &resizer_media_ops; |
1957 | ret = media_entity_init(me, RESIZER_PADS_NUM, pads, 0); | 1962 | ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); |
1958 | if (ret) | 1963 | if (ret) |
1959 | return ret; | 1964 | return ret; |
1960 | 1965 | ||
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c index 69b678ca40c0..ec46f366dd17 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c | |||
@@ -445,32 +445,32 @@ static int vpfe_register_entities(struct vpfe_device *vpfe_dev) | |||
445 | /* if entity has no pads (ex: amplifier), | 445 | /* if entity has no pads (ex: amplifier), |
446 | cant establish link */ | 446 | cant establish link */ |
447 | if (vpfe_dev->sd[i]->entity.num_pads) { | 447 | if (vpfe_dev->sd[i]->entity.num_pads) { |
448 | ret = media_entity_create_link(&vpfe_dev->sd[i]->entity, | 448 | ret = media_create_pad_link(&vpfe_dev->sd[i]->entity, |
449 | 0, &vpfe_dev->vpfe_isif.subdev.entity, | 449 | 0, &vpfe_dev->vpfe_isif.subdev.entity, |
450 | 0, flags); | 450 | 0, flags); |
451 | if (ret < 0) | 451 | if (ret < 0) |
452 | goto out_resizer_register; | 452 | goto out_resizer_register; |
453 | } | 453 | } |
454 | 454 | ||
455 | ret = media_entity_create_link(&vpfe_dev->vpfe_isif.subdev.entity, 1, | 455 | ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1, |
456 | &vpfe_dev->vpfe_ipipeif.subdev.entity, | 456 | &vpfe_dev->vpfe_ipipeif.subdev.entity, |
457 | 0, flags); | 457 | 0, flags); |
458 | if (ret < 0) | 458 | if (ret < 0) |
459 | goto out_resizer_register; | 459 | goto out_resizer_register; |
460 | 460 | ||
461 | ret = media_entity_create_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1, | 461 | ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1, |
462 | &vpfe_dev->vpfe_ipipe.subdev.entity, | 462 | &vpfe_dev->vpfe_ipipe.subdev.entity, |
463 | 0, flags); | 463 | 0, flags); |
464 | if (ret < 0) | 464 | if (ret < 0) |
465 | goto out_resizer_register; | 465 | goto out_resizer_register; |
466 | 466 | ||
467 | ret = media_entity_create_link(&vpfe_dev->vpfe_ipipe.subdev.entity, | 467 | ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity, |
468 | 1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity, | 468 | 1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity, |
469 | 0, flags); | 469 | 0, flags); |
470 | if (ret < 0) | 470 | if (ret < 0) |
471 | goto out_resizer_register; | 471 | goto out_resizer_register; |
472 | 472 | ||
473 | ret = media_entity_create_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1, | 473 | ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1, |
474 | &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity, | 474 | &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity, |
475 | 0, flags); | 475 | 0, flags); |
476 | if (ret < 0) | 476 | if (ret < 0) |
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index adb2bc8811ab..3ec7e65a3ffa 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c | |||
@@ -88,7 +88,7 @@ vpfe_video_remote_subdev(struct vpfe_video_device *video, u32 *pad) | |||
88 | { | 88 | { |
89 | struct media_pad *remote = media_entity_remote_pad(&video->pad); | 89 | struct media_pad *remote = media_entity_remote_pad(&video->pad); |
90 | 90 | ||
91 | if (remote == NULL || remote->entity->type != MEDIA_ENT_T_V4L2_SUBDEV) | 91 | if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) |
92 | return NULL; | 92 | return NULL; |
93 | if (pad) | 93 | if (pad) |
94 | *pad = remote->index; | 94 | *pad = remote->index; |
@@ -127,13 +127,14 @@ __vpfe_video_get_format(struct vpfe_video_device *video, | |||
127 | } | 127 | } |
128 | 128 | ||
129 | /* make a note of pipeline details */ | 129 | /* make a note of pipeline details */ |
130 | static void vpfe_prepare_pipeline(struct vpfe_video_device *video) | 130 | static int vpfe_prepare_pipeline(struct vpfe_video_device *video) |
131 | { | 131 | { |
132 | struct media_entity_graph graph; | ||
132 | struct media_entity *entity = &video->video_dev.entity; | 133 | struct media_entity *entity = &video->video_dev.entity; |
133 | struct media_device *mdev = entity->parent; | 134 | struct media_device *mdev = entity->graph_obj.mdev; |
134 | struct vpfe_pipeline *pipe = &video->pipe; | 135 | struct vpfe_pipeline *pipe = &video->pipe; |
135 | struct vpfe_video_device *far_end = NULL; | 136 | struct vpfe_video_device *far_end = NULL; |
136 | struct media_entity_graph graph; | 137 | int ret; |
137 | 138 | ||
138 | pipe->input_num = 0; | 139 | pipe->input_num = 0; |
139 | pipe->output_num = 0; | 140 | pipe->output_num = 0; |
@@ -144,11 +145,16 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video) | |||
144 | pipe->outputs[pipe->output_num++] = video; | 145 | pipe->outputs[pipe->output_num++] = video; |
145 | 146 | ||
146 | mutex_lock(&mdev->graph_mutex); | 147 | mutex_lock(&mdev->graph_mutex); |
148 | ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev); | ||
149 | if (ret) { | ||
150 | mutex_unlock(&video->lock); | ||
151 | return -ENOMEM; | ||
152 | } | ||
147 | media_entity_graph_walk_start(&graph, entity); | 153 | media_entity_graph_walk_start(&graph, entity); |
148 | while ((entity = media_entity_graph_walk_next(&graph))) { | 154 | while ((entity = media_entity_graph_walk_next(&graph))) { |
149 | if (entity == &video->video_dev.entity) | 155 | if (entity == &video->video_dev.entity) |
150 | continue; | 156 | continue; |
151 | if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) | 157 | if (!is_media_entity_v4l2_io(entity)) |
152 | continue; | 158 | continue; |
153 | far_end = to_vpfe_video(media_entity_to_video_device(entity)); | 159 | far_end = to_vpfe_video(media_entity_to_video_device(entity)); |
154 | if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | 160 | if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) |
@@ -156,7 +162,10 @@ static void vpfe_prepare_pipeline(struct vpfe_video_device *video) | |||
156 | else | 162 | else |
157 | pipe->outputs[pipe->output_num++] = far_end; | 163 | pipe->outputs[pipe->output_num++] = far_end; |
158 | } | 164 | } |
165 | media_entity_graph_walk_cleanup(&graph); | ||
159 | mutex_unlock(&mdev->graph_mutex); | 166 | mutex_unlock(&mdev->graph_mutex); |
167 | |||
168 | return 0; | ||
160 | } | 169 | } |
161 | 170 | ||
162 | /* update pipe state selected by user */ | 171 | /* update pipe state selected by user */ |
@@ -165,7 +174,9 @@ static int vpfe_update_pipe_state(struct vpfe_video_device *video) | |||
165 | struct vpfe_pipeline *pipe = &video->pipe; | 174 | struct vpfe_pipeline *pipe = &video->pipe; |
166 | int ret; | 175 | int ret; |
167 | 176 | ||
168 | vpfe_prepare_pipeline(video); | 177 | ret = vpfe_prepare_pipeline(video); |
178 | if (ret) | ||
179 | return ret; | ||
169 | 180 | ||
170 | /* Find out if there is any input video | 181 | /* Find out if there is any input video |
171 | if yes, it is single shot. | 182 | if yes, it is single shot. |
@@ -243,8 +254,7 @@ static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe) | |||
243 | 254 | ||
244 | /* Retrieve the source format */ | 255 | /* Retrieve the source format */ |
245 | pad = media_entity_remote_pad(pad); | 256 | pad = media_entity_remote_pad(pad); |
246 | if (pad == NULL || | 257 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
247 | pad->entity->type != MEDIA_ENT_T_V4L2_SUBDEV) | ||
248 | break; | 258 | break; |
249 | 259 | ||
250 | subdev = media_entity_to_v4l2_subdev(pad->entity); | 260 | subdev = media_entity_to_v4l2_subdev(pad->entity); |
@@ -277,29 +287,35 @@ static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe) | |||
277 | */ | 287 | */ |
278 | static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe) | 288 | static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe) |
279 | { | 289 | { |
280 | struct media_entity_graph graph; | ||
281 | struct media_entity *entity; | 290 | struct media_entity *entity; |
282 | struct v4l2_subdev *subdev; | 291 | struct v4l2_subdev *subdev; |
283 | struct media_device *mdev; | 292 | struct media_device *mdev; |
284 | int ret = 0; | 293 | int ret; |
285 | 294 | ||
286 | if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) | 295 | if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) |
287 | entity = vpfe_get_input_entity(pipe->outputs[0]); | 296 | entity = vpfe_get_input_entity(pipe->outputs[0]); |
288 | else | 297 | else |
289 | entity = &pipe->inputs[0]->video_dev.entity; | 298 | entity = &pipe->inputs[0]->video_dev.entity; |
290 | 299 | ||
291 | mdev = entity->parent; | 300 | mdev = entity->graph_obj.mdev; |
292 | mutex_lock(&mdev->graph_mutex); | 301 | mutex_lock(&mdev->graph_mutex); |
293 | media_entity_graph_walk_start(&graph, entity); | 302 | ret = media_entity_graph_walk_init(&pipe->graph, |
294 | while ((entity = media_entity_graph_walk_next(&graph))) { | 303 | entity->graph_obj.mdev); |
304 | if (ret) | ||
305 | goto out; | ||
306 | media_entity_graph_walk_start(&pipe->graph, entity); | ||
307 | while ((entity = media_entity_graph_walk_next(&pipe->graph))) { | ||
295 | 308 | ||
296 | if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) | 309 | if (!is_media_entity_v4l2_subdev(entity)) |
297 | continue; | 310 | continue; |
298 | subdev = media_entity_to_v4l2_subdev(entity); | 311 | subdev = media_entity_to_v4l2_subdev(entity); |
299 | ret = v4l2_subdev_call(subdev, video, s_stream, 1); | 312 | ret = v4l2_subdev_call(subdev, video, s_stream, 1); |
300 | if (ret < 0 && ret != -ENOIOCTLCMD) | 313 | if (ret < 0 && ret != -ENOIOCTLCMD) |
301 | break; | 314 | break; |
302 | } | 315 | } |
316 | out: | ||
317 | if (ret) | ||
318 | media_entity_graph_walk_cleanup(&pipe->graph); | ||
303 | mutex_unlock(&mdev->graph_mutex); | 319 | mutex_unlock(&mdev->graph_mutex); |
304 | return ret; | 320 | return ret; |
305 | } | 321 | } |
@@ -317,7 +333,6 @@ static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe) | |||
317 | */ | 333 | */ |
318 | static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe) | 334 | static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe) |
319 | { | 335 | { |
320 | struct media_entity_graph graph; | ||
321 | struct media_entity *entity; | 336 | struct media_entity *entity; |
322 | struct v4l2_subdev *subdev; | 337 | struct v4l2_subdev *subdev; |
323 | struct media_device *mdev; | 338 | struct media_device *mdev; |
@@ -328,13 +343,13 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe) | |||
328 | else | 343 | else |
329 | entity = &pipe->inputs[0]->video_dev.entity; | 344 | entity = &pipe->inputs[0]->video_dev.entity; |
330 | 345 | ||
331 | mdev = entity->parent; | 346 | mdev = entity->graph_obj.mdev; |
332 | mutex_lock(&mdev->graph_mutex); | 347 | mutex_lock(&mdev->graph_mutex); |
333 | media_entity_graph_walk_start(&graph, entity); | 348 | media_entity_graph_walk_start(&pipe->graph, entity); |
334 | 349 | ||
335 | while ((entity = media_entity_graph_walk_next(&graph))) { | 350 | while ((entity = media_entity_graph_walk_next(&pipe->graph))) { |
336 | 351 | ||
337 | if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) | 352 | if (!is_media_entity_v4l2_subdev(entity)) |
338 | continue; | 353 | continue; |
339 | subdev = media_entity_to_v4l2_subdev(entity); | 354 | subdev = media_entity_to_v4l2_subdev(entity); |
340 | ret = v4l2_subdev_call(subdev, video, s_stream, 0); | 355 | ret = v4l2_subdev_call(subdev, video, s_stream, 0); |
@@ -343,6 +358,7 @@ static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe) | |||
343 | } | 358 | } |
344 | mutex_unlock(&mdev->graph_mutex); | 359 | mutex_unlock(&mdev->graph_mutex); |
345 | 360 | ||
361 | media_entity_graph_walk_cleanup(&pipe->graph); | ||
346 | return ret ? -ETIMEDOUT : 0; | 362 | return ret ? -ETIMEDOUT : 0; |
347 | } | 363 | } |
348 | 364 | ||
@@ -1600,8 +1616,8 @@ int vpfe_video_init(struct vpfe_video_device *video, const char *name) | |||
1600 | spin_lock_init(&video->irqlock); | 1616 | spin_lock_init(&video->irqlock); |
1601 | spin_lock_init(&video->dma_queue_lock); | 1617 | spin_lock_init(&video->dma_queue_lock); |
1602 | mutex_init(&video->lock); | 1618 | mutex_init(&video->lock); |
1603 | ret = media_entity_init(&video->video_dev.entity, | 1619 | ret = media_entity_pads_init(&video->video_dev.entity, |
1604 | 1, &video->pad, 0); | 1620 | 1, &video->pad); |
1605 | if (ret < 0) | 1621 | if (ret < 0) |
1606 | return ret; | 1622 | return ret; |
1607 | 1623 | ||
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.h b/drivers/staging/media/davinci_vpfe/vpfe_video.h index 673cefe3ef61..653334d537d3 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.h +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.h | |||
@@ -52,6 +52,7 @@ enum vpfe_video_state { | |||
52 | struct vpfe_pipeline { | 52 | struct vpfe_pipeline { |
53 | /* media pipeline */ | 53 | /* media pipeline */ |
54 | struct media_pipeline *pipe; | 54 | struct media_pipeline *pipe; |
55 | struct media_entity_graph graph; | ||
55 | /* state of the pipeline, continuous, | 56 | /* state of the pipeline, continuous, |
56 | * single-shot or stopped | 57 | * single-shot or stopped |
57 | */ | 58 | */ |
diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index e27a988540a6..30b473cfb020 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c | |||
@@ -389,15 +389,15 @@ static irqreturn_t iss_isr(int irq, void *_iss) | |||
389 | * | 389 | * |
390 | * Return the total number of users of all video device nodes in the pipeline. | 390 | * Return the total number of users of all video device nodes in the pipeline. |
391 | */ | 391 | */ |
392 | static int iss_pipeline_pm_use_count(struct media_entity *entity) | 392 | static int iss_pipeline_pm_use_count(struct media_entity *entity, |
393 | struct media_entity_graph *graph) | ||
393 | { | 394 | { |
394 | struct media_entity_graph graph; | ||
395 | int use = 0; | 395 | int use = 0; |
396 | 396 | ||
397 | media_entity_graph_walk_start(&graph, entity); | 397 | media_entity_graph_walk_start(graph, entity); |
398 | 398 | ||
399 | while ((entity = media_entity_graph_walk_next(&graph))) { | 399 | while ((entity = media_entity_graph_walk_next(graph))) { |
400 | if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) | 400 | if (is_media_entity_v4l2_io(entity)) |
401 | use += entity->use_count; | 401 | use += entity->use_count; |
402 | } | 402 | } |
403 | 403 | ||
@@ -419,7 +419,7 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change) | |||
419 | { | 419 | { |
420 | struct v4l2_subdev *subdev; | 420 | struct v4l2_subdev *subdev; |
421 | 421 | ||
422 | subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV | 422 | subdev = is_media_entity_v4l2_subdev(entity) |
423 | ? media_entity_to_v4l2_subdev(entity) : NULL; | 423 | ? media_entity_to_v4l2_subdev(entity) : NULL; |
424 | 424 | ||
425 | if (entity->use_count == 0 && change > 0 && subdev) { | 425 | if (entity->use_count == 0 && change > 0 && subdev) { |
@@ -449,29 +449,29 @@ static int iss_pipeline_pm_power_one(struct media_entity *entity, int change) | |||
449 | * | 449 | * |
450 | * Return 0 on success or a negative error code on failure. | 450 | * Return 0 on success or a negative error code on failure. |
451 | */ | 451 | */ |
452 | static int iss_pipeline_pm_power(struct media_entity *entity, int change) | 452 | static int iss_pipeline_pm_power(struct media_entity *entity, int change, |
453 | struct media_entity_graph *graph) | ||
453 | { | 454 | { |
454 | struct media_entity_graph graph; | ||
455 | struct media_entity *first = entity; | 455 | struct media_entity *first = entity; |
456 | int ret = 0; | 456 | int ret = 0; |
457 | 457 | ||
458 | if (!change) | 458 | if (!change) |
459 | return 0; | 459 | return 0; |
460 | 460 | ||
461 | media_entity_graph_walk_start(&graph, entity); | 461 | media_entity_graph_walk_start(graph, entity); |
462 | 462 | ||
463 | while (!ret && (entity = media_entity_graph_walk_next(&graph))) | 463 | while (!ret && (entity = media_entity_graph_walk_next(graph))) |
464 | if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) | 464 | if (is_media_entity_v4l2_subdev(entity)) |
465 | ret = iss_pipeline_pm_power_one(entity, change); | 465 | ret = iss_pipeline_pm_power_one(entity, change); |
466 | 466 | ||
467 | if (!ret) | 467 | if (!ret) |
468 | return 0; | 468 | return 0; |
469 | 469 | ||
470 | media_entity_graph_walk_start(&graph, first); | 470 | media_entity_graph_walk_start(graph, first); |
471 | 471 | ||
472 | while ((first = media_entity_graph_walk_next(&graph)) && | 472 | while ((first = media_entity_graph_walk_next(graph)) && |
473 | first != entity) | 473 | first != entity) |
474 | if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE) | 474 | if (is_media_entity_v4l2_subdev(first)) |
475 | iss_pipeline_pm_power_one(first, -change); | 475 | iss_pipeline_pm_power_one(first, -change); |
476 | 476 | ||
477 | return ret; | 477 | return ret; |
@@ -489,23 +489,24 @@ static int iss_pipeline_pm_power(struct media_entity *entity, int change) | |||
489 | * off is assumed to never fail. No failure can occur when the use parameter is | 489 | * off is assumed to never fail. No failure can occur when the use parameter is |
490 | * set to 0. | 490 | * set to 0. |
491 | */ | 491 | */ |
492 | int omap4iss_pipeline_pm_use(struct media_entity *entity, int use) | 492 | int omap4iss_pipeline_pm_use(struct media_entity *entity, int use, |
493 | struct media_entity_graph *graph) | ||
493 | { | 494 | { |
494 | int change = use ? 1 : -1; | 495 | int change = use ? 1 : -1; |
495 | int ret; | 496 | int ret; |
496 | 497 | ||
497 | mutex_lock(&entity->parent->graph_mutex); | 498 | mutex_lock(&entity->graph_obj.mdev->graph_mutex); |
498 | 499 | ||
499 | /* Apply use count to node. */ | 500 | /* Apply use count to node. */ |
500 | entity->use_count += change; | 501 | entity->use_count += change; |
501 | WARN_ON(entity->use_count < 0); | 502 | WARN_ON(entity->use_count < 0); |
502 | 503 | ||
503 | /* Apply power change to connected non-nodes. */ | 504 | /* Apply power change to connected non-nodes. */ |
504 | ret = iss_pipeline_pm_power(entity, change); | 505 | ret = iss_pipeline_pm_power(entity, change, graph); |
505 | if (ret < 0) | 506 | if (ret < 0) |
506 | entity->use_count -= change; | 507 | entity->use_count -= change; |
507 | 508 | ||
508 | mutex_unlock(&entity->parent->graph_mutex); | 509 | mutex_unlock(&entity->graph_obj.mdev->graph_mutex); |
509 | 510 | ||
510 | return ret; | 511 | return ret; |
511 | } | 512 | } |
@@ -526,34 +527,48 @@ int omap4iss_pipeline_pm_use(struct media_entity *entity, int use) | |||
526 | static int iss_pipeline_link_notify(struct media_link *link, u32 flags, | 527 | static int iss_pipeline_link_notify(struct media_link *link, u32 flags, |
527 | unsigned int notification) | 528 | unsigned int notification) |
528 | { | 529 | { |
530 | struct media_entity_graph *graph = | ||
531 | &container_of(link->graph_obj.mdev, struct iss_device, | ||
532 | media_dev)->pm_count_graph; | ||
529 | struct media_entity *source = link->source->entity; | 533 | struct media_entity *source = link->source->entity; |
530 | struct media_entity *sink = link->sink->entity; | 534 | struct media_entity *sink = link->sink->entity; |
531 | int source_use = iss_pipeline_pm_use_count(source); | 535 | int source_use; |
532 | int sink_use = iss_pipeline_pm_use_count(sink); | 536 | int sink_use; |
533 | int ret; | 537 | int ret; |
534 | 538 | ||
539 | if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) { | ||
540 | ret = media_entity_graph_walk_init(graph, | ||
541 | link->graph_obj.mdev); | ||
542 | if (ret) | ||
543 | return ret; | ||
544 | } | ||
545 | |||
546 | source_use = iss_pipeline_pm_use_count(source, graph); | ||
547 | sink_use = iss_pipeline_pm_use_count(sink, graph); | ||
548 | |||
535 | if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && | 549 | if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && |
536 | !(link->flags & MEDIA_LNK_FL_ENABLED)) { | 550 | !(flags & MEDIA_LNK_FL_ENABLED)) { |
537 | /* Powering off entities is assumed to never fail. */ | 551 | /* Powering off entities is assumed to never fail. */ |
538 | iss_pipeline_pm_power(source, -sink_use); | 552 | iss_pipeline_pm_power(source, -sink_use, graph); |
539 | iss_pipeline_pm_power(sink, -source_use); | 553 | iss_pipeline_pm_power(sink, -source_use, graph); |
540 | return 0; | 554 | return 0; |
541 | } | 555 | } |
542 | 556 | ||
543 | if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && | 557 | if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH && |
544 | (flags & MEDIA_LNK_FL_ENABLED)) { | 558 | (flags & MEDIA_LNK_FL_ENABLED)) { |
545 | ret = iss_pipeline_pm_power(source, sink_use); | 559 | ret = iss_pipeline_pm_power(source, sink_use, graph); |
546 | if (ret < 0) | 560 | if (ret < 0) |
547 | return ret; | 561 | return ret; |
548 | 562 | ||
549 | ret = iss_pipeline_pm_power(sink, source_use); | 563 | ret = iss_pipeline_pm_power(sink, source_use, graph); |
550 | if (ret < 0) | 564 | if (ret < 0) |
551 | iss_pipeline_pm_power(source, -sink_use); | 565 | iss_pipeline_pm_power(source, -sink_use, graph); |
552 | |||
553 | return ret; | ||
554 | } | 566 | } |
555 | 567 | ||
556 | return 0; | 568 | if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH) |
569 | media_entity_graph_walk_cleanup(graph); | ||
570 | |||
571 | return ret; | ||
557 | } | 572 | } |
558 | 573 | ||
559 | /* ----------------------------------------------------------------------------- | 574 | /* ----------------------------------------------------------------------------- |
@@ -590,8 +605,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe, | |||
590 | break; | 605 | break; |
591 | 606 | ||
592 | pad = media_entity_remote_pad(pad); | 607 | pad = media_entity_remote_pad(pad); |
593 | if (!pad || | 608 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
594 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
595 | break; | 609 | break; |
596 | 610 | ||
597 | entity = pad->entity; | 611 | entity = pad->entity; |
@@ -607,7 +621,7 @@ static int iss_pipeline_disable(struct iss_pipeline *pipe, | |||
607 | * crashed. Mark it as such, the ISS will be reset when | 621 | * crashed. Mark it as such, the ISS will be reset when |
608 | * applications will release it. | 622 | * applications will release it. |
609 | */ | 623 | */ |
610 | iss->crashed |= 1U << subdev->entity.id; | 624 | media_entity_enum_set(&iss->crashed, &subdev->entity); |
611 | failure = -ETIMEDOUT; | 625 | failure = -ETIMEDOUT; |
612 | } | 626 | } |
613 | } | 627 | } |
@@ -642,7 +656,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe, | |||
642 | * pipeline won't start anyway (those entities would then likely fail to | 656 | * pipeline won't start anyway (those entities would then likely fail to |
643 | * stop, making the problem worse). | 657 | * stop, making the problem worse). |
644 | */ | 658 | */ |
645 | if (pipe->entities & iss->crashed) | 659 | if (media_entity_enum_intersects(&pipe->ent_enum, &iss->crashed)) |
646 | return -EIO; | 660 | return -EIO; |
647 | 661 | ||
648 | spin_lock_irqsave(&pipe->lock, flags); | 662 | spin_lock_irqsave(&pipe->lock, flags); |
@@ -658,8 +672,7 @@ static int iss_pipeline_enable(struct iss_pipeline *pipe, | |||
658 | break; | 672 | break; |
659 | 673 | ||
660 | pad = media_entity_remote_pad(pad); | 674 | pad = media_entity_remote_pad(pad); |
661 | if (!pad || | 675 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) |
662 | media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
663 | break; | 676 | break; |
664 | 677 | ||
665 | entity = pad->entity; | 678 | entity = pad->entity; |
@@ -763,7 +776,8 @@ static int iss_reset(struct iss_device *iss) | |||
763 | return -ETIMEDOUT; | 776 | return -ETIMEDOUT; |
764 | } | 777 | } |
765 | 778 | ||
766 | iss->crashed = 0; | 779 | media_entity_enum_zero(&iss->crashed); |
780 | |||
767 | return 0; | 781 | return 0; |
768 | } | 782 | } |
769 | 783 | ||
@@ -1092,7 +1106,7 @@ void omap4iss_put(struct iss_device *iss) | |||
1092 | * be worth investigating whether resetting the ISP only can't | 1106 | * be worth investigating whether resetting the ISP only can't |
1093 | * fix the problem in some cases. | 1107 | * fix the problem in some cases. |
1094 | */ | 1108 | */ |
1095 | if (iss->crashed) | 1109 | if (!media_entity_enum_empty(&iss->crashed)) |
1096 | iss_reset(iss); | 1110 | iss_reset(iss); |
1097 | iss_disable_clocks(iss); | 1111 | iss_disable_clocks(iss); |
1098 | } | 1112 | } |
@@ -1259,7 +1273,7 @@ static int iss_register_entities(struct iss_device *iss) | |||
1259 | goto done; | 1273 | goto done; |
1260 | } | 1274 | } |
1261 | 1275 | ||
1262 | ret = media_entity_create_link(&sensor->entity, 0, input, pad, | 1276 | ret = media_create_pad_link(&sensor->entity, 0, input, pad, |
1263 | flags); | 1277 | flags); |
1264 | if (ret < 0) | 1278 | if (ret < 0) |
1265 | goto done; | 1279 | goto done; |
@@ -1274,6 +1288,68 @@ done: | |||
1274 | return ret; | 1288 | return ret; |
1275 | } | 1289 | } |
1276 | 1290 | ||
1291 | /* | ||
1292 | * iss_create_links() - Pads links creation for the subdevices | ||
1293 | * @iss : Pointer to ISS device | ||
1294 | * | ||
1295 | * return negative error code or zero on success | ||
1296 | */ | ||
1297 | static int iss_create_links(struct iss_device *iss) | ||
1298 | { | ||
1299 | int ret; | ||
1300 | |||
1301 | ret = omap4iss_csi2_create_links(iss); | ||
1302 | if (ret < 0) { | ||
1303 | dev_err(iss->dev, "CSI2 pads links creation failed\n"); | ||
1304 | return ret; | ||
1305 | } | ||
1306 | |||
1307 | ret = omap4iss_ipipeif_create_links(iss); | ||
1308 | if (ret < 0) { | ||
1309 | dev_err(iss->dev, "ISP IPIPEIF pads links creation failed\n"); | ||
1310 | return ret; | ||
1311 | } | ||
1312 | |||
1313 | ret = omap4iss_resizer_create_links(iss); | ||
1314 | if (ret < 0) { | ||
1315 | dev_err(iss->dev, "ISP RESIZER pads links creation failed\n"); | ||
1316 | return ret; | ||
1317 | } | ||
1318 | |||
1319 | /* Connect the submodules. */ | ||
1320 | ret = media_create_pad_link( | ||
1321 | &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE, | ||
1322 | &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); | ||
1323 | if (ret < 0) | ||
1324 | return ret; | ||
1325 | |||
1326 | ret = media_create_pad_link( | ||
1327 | &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE, | ||
1328 | &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); | ||
1329 | if (ret < 0) | ||
1330 | return ret; | ||
1331 | |||
1332 | ret = media_create_pad_link( | ||
1333 | &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, | ||
1334 | &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); | ||
1335 | if (ret < 0) | ||
1336 | return ret; | ||
1337 | |||
1338 | ret = media_create_pad_link( | ||
1339 | &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, | ||
1340 | &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0); | ||
1341 | if (ret < 0) | ||
1342 | return ret; | ||
1343 | |||
1344 | ret = media_create_pad_link( | ||
1345 | &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP, | ||
1346 | &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); | ||
1347 | if (ret < 0) | ||
1348 | return ret; | ||
1349 | |||
1350 | return 0; | ||
1351 | }; | ||
1352 | |||
1277 | static void iss_cleanup_modules(struct iss_device *iss) | 1353 | static void iss_cleanup_modules(struct iss_device *iss) |
1278 | { | 1354 | { |
1279 | omap4iss_csi2_cleanup(iss); | 1355 | omap4iss_csi2_cleanup(iss); |
@@ -1316,41 +1392,8 @@ static int iss_initialize_modules(struct iss_device *iss) | |||
1316 | goto error_resizer; | 1392 | goto error_resizer; |
1317 | } | 1393 | } |
1318 | 1394 | ||
1319 | /* Connect the submodules. */ | ||
1320 | ret = media_entity_create_link( | ||
1321 | &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE, | ||
1322 | &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); | ||
1323 | if (ret < 0) | ||
1324 | goto error_link; | ||
1325 | |||
1326 | ret = media_entity_create_link( | ||
1327 | &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE, | ||
1328 | &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); | ||
1329 | if (ret < 0) | ||
1330 | goto error_link; | ||
1331 | |||
1332 | ret = media_entity_create_link( | ||
1333 | &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, | ||
1334 | &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); | ||
1335 | if (ret < 0) | ||
1336 | goto error_link; | ||
1337 | |||
1338 | ret = media_entity_create_link( | ||
1339 | &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, | ||
1340 | &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0); | ||
1341 | if (ret < 0) | ||
1342 | goto error_link; | ||
1343 | |||
1344 | ret = media_entity_create_link( | ||
1345 | &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP, | ||
1346 | &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); | ||
1347 | if (ret < 0) | ||
1348 | goto error_link; | ||
1349 | |||
1350 | return 0; | 1395 | return 0; |
1351 | 1396 | ||
1352 | error_link: | ||
1353 | omap4iss_resizer_cleanup(iss); | ||
1354 | error_resizer: | 1397 | error_resizer: |
1355 | omap4iss_ipipe_cleanup(iss); | 1398 | omap4iss_ipipe_cleanup(iss); |
1356 | error_ipipe: | 1399 | error_ipipe: |
@@ -1464,10 +1507,21 @@ static int iss_probe(struct platform_device *pdev) | |||
1464 | if (ret < 0) | 1507 | if (ret < 0) |
1465 | goto error_modules; | 1508 | goto error_modules; |
1466 | 1509 | ||
1510 | ret = media_entity_enum_init(&iss->crashed, &iss->media_dev); | ||
1511 | if (ret) | ||
1512 | goto error_entities; | ||
1513 | |||
1514 | ret = iss_create_links(iss); | ||
1515 | if (ret < 0) | ||
1516 | goto error_entities; | ||
1517 | |||
1467 | omap4iss_put(iss); | 1518 | omap4iss_put(iss); |
1468 | 1519 | ||
1469 | return 0; | 1520 | return 0; |
1470 | 1521 | ||
1522 | error_entities: | ||
1523 | iss_unregister_entities(iss); | ||
1524 | media_entity_enum_cleanup(&iss->crashed); | ||
1471 | error_modules: | 1525 | error_modules: |
1472 | iss_cleanup_modules(iss); | 1526 | iss_cleanup_modules(iss); |
1473 | error_iss: | 1527 | error_iss: |
@@ -1485,6 +1539,7 @@ static int iss_remove(struct platform_device *pdev) | |||
1485 | struct iss_device *iss = platform_get_drvdata(pdev); | 1539 | struct iss_device *iss = platform_get_drvdata(pdev); |
1486 | 1540 | ||
1487 | iss_unregister_entities(iss); | 1541 | iss_unregister_entities(iss); |
1542 | media_entity_enum_cleanup(&iss->crashed); | ||
1488 | iss_cleanup_modules(iss); | 1543 | iss_cleanup_modules(iss); |
1489 | 1544 | ||
1490 | return 0; | 1545 | return 0; |
diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h index 5929357fe687..05f08a3caa19 100644 --- a/drivers/staging/media/omap4iss/iss.h +++ b/drivers/staging/media/omap4iss/iss.h | |||
@@ -82,11 +82,12 @@ struct iss_reg { | |||
82 | /* | 82 | /* |
83 | * struct iss_device - ISS device structure. | 83 | * struct iss_device - ISS device structure. |
84 | * @syscon: Regmap for the syscon register space | 84 | * @syscon: Regmap for the syscon register space |
85 | * @crashed: Bitmask of crashed entities (indexed by entity ID) | 85 | * @crashed: Crashed entities |
86 | */ | 86 | */ |
87 | struct iss_device { | 87 | struct iss_device { |
88 | struct v4l2_device v4l2_dev; | 88 | struct v4l2_device v4l2_dev; |
89 | struct media_device media_dev; | 89 | struct media_device media_dev; |
90 | struct media_entity_graph pm_count_graph; | ||
90 | struct device *dev; | 91 | struct device *dev; |
91 | u32 revision; | 92 | u32 revision; |
92 | 93 | ||
@@ -101,7 +102,7 @@ struct iss_device { | |||
101 | u64 raw_dmamask; | 102 | u64 raw_dmamask; |
102 | 103 | ||
103 | struct mutex iss_mutex; /* For handling ref_count field */ | 104 | struct mutex iss_mutex; /* For handling ref_count field */ |
104 | unsigned int crashed; | 105 | struct media_entity_enum crashed; |
105 | int has_context; | 106 | int has_context; |
106 | int ref_count; | 107 | int ref_count; |
107 | 108 | ||
@@ -151,7 +152,8 @@ void omap4iss_isp_subclk_enable(struct iss_device *iss, | |||
151 | void omap4iss_isp_subclk_disable(struct iss_device *iss, | 152 | void omap4iss_isp_subclk_disable(struct iss_device *iss, |
152 | enum iss_isp_subclk_resource res); | 153 | enum iss_isp_subclk_resource res); |
153 | 154 | ||
154 | int omap4iss_pipeline_pm_use(struct media_entity *entity, int use); | 155 | int omap4iss_pipeline_pm_use(struct media_entity *entity, int use, |
156 | struct media_entity_graph *graph); | ||
155 | 157 | ||
156 | int omap4iss_register_entities(struct platform_device *pdev, | 158 | int omap4iss_register_entities(struct platform_device *pdev, |
157 | struct v4l2_device *v4l2_dev); | 159 | struct v4l2_device *v4l2_dev); |
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index b941035139ae..aaca39d751a5 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c | |||
@@ -1170,14 +1170,19 @@ static int csi2_link_setup(struct media_entity *entity, | |||
1170 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 1170 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
1171 | struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); | 1171 | struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); |
1172 | struct iss_csi2_ctrl_cfg *ctrl = &csi2->ctrl; | 1172 | struct iss_csi2_ctrl_cfg *ctrl = &csi2->ctrl; |
1173 | unsigned int index = local->index; | ||
1174 | |||
1175 | /* FIXME: this is actually a hack! */ | ||
1176 | if (is_media_entity_v4l2_subdev(remote->entity)) | ||
1177 | index |= 2 << 16; | ||
1173 | 1178 | ||
1174 | /* | 1179 | /* |
1175 | * The ISS core doesn't support pipelines with multiple video outputs. | 1180 | * The ISS core doesn't support pipelines with multiple video outputs. |
1176 | * Revisit this when it will be implemented, and return -EBUSY for now. | 1181 | * Revisit this when it will be implemented, and return -EBUSY for now. |
1177 | */ | 1182 | */ |
1178 | 1183 | ||
1179 | switch (local->index | media_entity_type(remote->entity)) { | 1184 | switch (index) { |
1180 | case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE: | 1185 | case CSI2_PAD_SOURCE: |
1181 | if (flags & MEDIA_LNK_FL_ENABLED) { | 1186 | if (flags & MEDIA_LNK_FL_ENABLED) { |
1182 | if (csi2->output & ~CSI2_OUTPUT_MEMORY) | 1187 | if (csi2->output & ~CSI2_OUTPUT_MEMORY) |
1183 | return -EBUSY; | 1188 | return -EBUSY; |
@@ -1187,7 +1192,7 @@ static int csi2_link_setup(struct media_entity *entity, | |||
1187 | } | 1192 | } |
1188 | break; | 1193 | break; |
1189 | 1194 | ||
1190 | case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV: | 1195 | case CSI2_PAD_SOURCE | 2 << 16: |
1191 | if (flags & MEDIA_LNK_FL_ENABLED) { | 1196 | if (flags & MEDIA_LNK_FL_ENABLED) { |
1192 | if (csi2->output & ~CSI2_OUTPUT_IPIPEIF) | 1197 | if (csi2->output & ~CSI2_OUTPUT_IPIPEIF) |
1193 | return -EBUSY; | 1198 | return -EBUSY; |
@@ -1271,7 +1276,7 @@ static int csi2_init_entities(struct iss_csi2_device *csi2, const char *subname) | |||
1271 | pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; | 1276 | pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK; |
1272 | 1277 | ||
1273 | me->ops = &csi2_media_ops; | 1278 | me->ops = &csi2_media_ops; |
1274 | ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0); | 1279 | ret = media_entity_pads_init(me, CSI2_PADS_NUM, pads); |
1275 | if (ret < 0) | 1280 | if (ret < 0) |
1276 | return ret; | 1281 | return ret; |
1277 | 1282 | ||
@@ -1290,16 +1295,8 @@ static int csi2_init_entities(struct iss_csi2_device *csi2, const char *subname) | |||
1290 | if (ret < 0) | 1295 | if (ret < 0) |
1291 | goto error_video; | 1296 | goto error_video; |
1292 | 1297 | ||
1293 | /* Connect the CSI2 subdev to the video node. */ | ||
1294 | ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE, | ||
1295 | &csi2->video_out.video.entity, 0, 0); | ||
1296 | if (ret < 0) | ||
1297 | goto error_link; | ||
1298 | |||
1299 | return 0; | 1298 | return 0; |
1300 | 1299 | ||
1301 | error_link: | ||
1302 | omap4iss_video_cleanup(&csi2->video_out); | ||
1303 | error_video: | 1300 | error_video: |
1304 | media_entity_cleanup(&csi2->subdev.entity); | 1301 | media_entity_cleanup(&csi2->subdev.entity); |
1305 | return ret; | 1302 | return ret; |
@@ -1342,6 +1339,33 @@ int omap4iss_csi2_init(struct iss_device *iss) | |||
1342 | } | 1339 | } |
1343 | 1340 | ||
1344 | /* | 1341 | /* |
1342 | * omap4iss_csi2_create_links() - CSI2 pads links creation | ||
1343 | * @iss: Pointer to ISS device | ||
1344 | * | ||
1345 | * return negative error code or zero on success | ||
1346 | */ | ||
1347 | int omap4iss_csi2_create_links(struct iss_device *iss) | ||
1348 | { | ||
1349 | struct iss_csi2_device *csi2a = &iss->csi2a; | ||
1350 | struct iss_csi2_device *csi2b = &iss->csi2b; | ||
1351 | int ret; | ||
1352 | |||
1353 | /* Connect the CSI2a subdev to the video node. */ | ||
1354 | ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE, | ||
1355 | &csi2a->video_out.video.entity, 0, 0); | ||
1356 | if (ret < 0) | ||
1357 | return ret; | ||
1358 | |||
1359 | /* Connect the CSI2b subdev to the video node. */ | ||
1360 | ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE, | ||
1361 | &csi2b->video_out.video.entity, 0, 0); | ||
1362 | if (ret < 0) | ||
1363 | return ret; | ||
1364 | |||
1365 | return 0; | ||
1366 | } | ||
1367 | |||
1368 | /* | ||
1345 | * omap4iss_csi2_cleanup - Routine for module driver cleanup | 1369 | * omap4iss_csi2_cleanup - Routine for module driver cleanup |
1346 | */ | 1370 | */ |
1347 | void omap4iss_csi2_cleanup(struct iss_device *iss) | 1371 | void omap4iss_csi2_cleanup(struct iss_device *iss) |
diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h index f2f5343b4a80..24ab378d469f 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.h +++ b/drivers/staging/media/omap4iss/iss_csi2.h | |||
@@ -151,6 +151,7 @@ struct iss_csi2_device { | |||
151 | void omap4iss_csi2_isr(struct iss_csi2_device *csi2); | 151 | void omap4iss_csi2_isr(struct iss_csi2_device *csi2); |
152 | int omap4iss_csi2_reset(struct iss_csi2_device *csi2); | 152 | int omap4iss_csi2_reset(struct iss_csi2_device *csi2); |
153 | int omap4iss_csi2_init(struct iss_device *iss); | 153 | int omap4iss_csi2_init(struct iss_device *iss); |
154 | int omap4iss_csi2_create_links(struct iss_device *iss); | ||
154 | void omap4iss_csi2_cleanup(struct iss_device *iss); | 155 | void omap4iss_csi2_cleanup(struct iss_device *iss); |
155 | void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2); | 156 | void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2); |
156 | int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2, | 157 | int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2, |
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c index dd0abeffd893..d38782e8e84c 100644 --- a/drivers/staging/media/omap4iss/iss_ipipe.c +++ b/drivers/staging/media/omap4iss/iss_ipipe.c | |||
@@ -447,8 +447,11 @@ static int ipipe_link_setup(struct media_entity *entity, | |||
447 | struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); | 447 | struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd); |
448 | struct iss_device *iss = to_iss_device(ipipe); | 448 | struct iss_device *iss = to_iss_device(ipipe); |
449 | 449 | ||
450 | switch (local->index | media_entity_type(remote->entity)) { | 450 | if (!is_media_entity_v4l2_subdev(remote->entity)) |
451 | case IPIPE_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 451 | return -EINVAL; |
452 | |||
453 | switch (local->index) { | ||
454 | case IPIPE_PAD_SINK: | ||
452 | /* Read from IPIPEIF. */ | 455 | /* Read from IPIPEIF. */ |
453 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 456 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
454 | ipipe->input = IPIPE_INPUT_NONE; | 457 | ipipe->input = IPIPE_INPUT_NONE; |
@@ -463,7 +466,7 @@ static int ipipe_link_setup(struct media_entity *entity, | |||
463 | 466 | ||
464 | break; | 467 | break; |
465 | 468 | ||
466 | case IPIPE_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV: | 469 | case IPIPE_PAD_SOURCE_VP: |
467 | /* Send to RESIZER */ | 470 | /* Send to RESIZER */ |
468 | if (flags & MEDIA_LNK_FL_ENABLED) { | 471 | if (flags & MEDIA_LNK_FL_ENABLED) { |
469 | if (ipipe->output & ~IPIPE_OUTPUT_VP) | 472 | if (ipipe->output & ~IPIPE_OUTPUT_VP) |
@@ -513,7 +516,7 @@ static int ipipe_init_entities(struct iss_ipipe_device *ipipe) | |||
513 | pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; | 516 | pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; |
514 | 517 | ||
515 | me->ops = &ipipe_media_ops; | 518 | me->ops = &ipipe_media_ops; |
516 | ret = media_entity_init(me, IPIPE_PADS_NUM, pads, 0); | 519 | ret = media_entity_pads_init(me, IPIPE_PADS_NUM, pads); |
517 | if (ret < 0) | 520 | if (ret < 0) |
518 | return ret; | 521 | return ret; |
519 | 522 | ||
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index 5f9e449e7007..23de8330731d 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c | |||
@@ -662,9 +662,14 @@ static int ipipeif_link_setup(struct media_entity *entity, | |||
662 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 662 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
663 | struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); | 663 | struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); |
664 | struct iss_device *iss = to_iss_device(ipipeif); | 664 | struct iss_device *iss = to_iss_device(ipipeif); |
665 | unsigned int index = local->index; | ||
665 | 666 | ||
666 | switch (local->index | media_entity_type(remote->entity)) { | 667 | /* FIXME: this is actually a hack! */ |
667 | case IPIPEIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 668 | if (is_media_entity_v4l2_subdev(remote->entity)) |
669 | index |= 2 << 16; | ||
670 | |||
671 | switch (index) { | ||
672 | case IPIPEIF_PAD_SINK | 2 << 16: | ||
668 | /* Read from the sensor CSI2a or CSI2b. */ | 673 | /* Read from the sensor CSI2a or CSI2b. */ |
669 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 674 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
670 | ipipeif->input = IPIPEIF_INPUT_NONE; | 675 | ipipeif->input = IPIPEIF_INPUT_NONE; |
@@ -681,7 +686,7 @@ static int ipipeif_link_setup(struct media_entity *entity, | |||
681 | 686 | ||
682 | break; | 687 | break; |
683 | 688 | ||
684 | case IPIPEIF_PAD_SOURCE_ISIF_SF | MEDIA_ENT_T_DEVNODE: | 689 | case IPIPEIF_PAD_SOURCE_ISIF_SF: |
685 | /* Write to memory */ | 690 | /* Write to memory */ |
686 | if (flags & MEDIA_LNK_FL_ENABLED) { | 691 | if (flags & MEDIA_LNK_FL_ENABLED) { |
687 | if (ipipeif->output & ~IPIPEIF_OUTPUT_MEMORY) | 692 | if (ipipeif->output & ~IPIPEIF_OUTPUT_MEMORY) |
@@ -692,7 +697,7 @@ static int ipipeif_link_setup(struct media_entity *entity, | |||
692 | } | 697 | } |
693 | break; | 698 | break; |
694 | 699 | ||
695 | case IPIPEIF_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV: | 700 | case IPIPEIF_PAD_SOURCE_VP | 2 << 16: |
696 | /* Send to IPIPE/RESIZER */ | 701 | /* Send to IPIPE/RESIZER */ |
697 | if (flags & MEDIA_LNK_FL_ENABLED) { | 702 | if (flags & MEDIA_LNK_FL_ENABLED) { |
698 | if (ipipeif->output & ~IPIPEIF_OUTPUT_VP) | 703 | if (ipipeif->output & ~IPIPEIF_OUTPUT_VP) |
@@ -743,7 +748,7 @@ static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif) | |||
743 | pads[IPIPEIF_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; | 748 | pads[IPIPEIF_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; |
744 | 749 | ||
745 | me->ops = &ipipeif_media_ops; | 750 | me->ops = &ipipeif_media_ops; |
746 | ret = media_entity_init(me, IPIPEIF_PADS_NUM, pads, 0); | 751 | ret = media_entity_pads_init(me, IPIPEIF_PADS_NUM, pads); |
747 | if (ret < 0) | 752 | if (ret < 0) |
748 | return ret; | 753 | return ret; |
749 | 754 | ||
@@ -757,18 +762,7 @@ static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif) | |||
757 | ipipeif->video_out.bpl_zero_padding = 1; | 762 | ipipeif->video_out.bpl_zero_padding = 1; |
758 | ipipeif->video_out.bpl_max = 0x1ffe0; | 763 | ipipeif->video_out.bpl_max = 0x1ffe0; |
759 | 764 | ||
760 | ret = omap4iss_video_init(&ipipeif->video_out, "ISP IPIPEIF"); | 765 | return omap4iss_video_init(&ipipeif->video_out, "ISP IPIPEIF"); |
761 | if (ret < 0) | ||
762 | return ret; | ||
763 | |||
764 | /* Connect the IPIPEIF subdev to the video node. */ | ||
765 | ret = media_entity_create_link(&ipipeif->subdev.entity, | ||
766 | IPIPEIF_PAD_SOURCE_ISIF_SF, | ||
767 | &ipipeif->video_out.video.entity, 0, 0); | ||
768 | if (ret < 0) | ||
769 | return ret; | ||
770 | |||
771 | return 0; | ||
772 | } | 766 | } |
773 | 767 | ||
774 | void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif) | 768 | void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif) |
@@ -821,6 +815,22 @@ int omap4iss_ipipeif_init(struct iss_device *iss) | |||
821 | } | 815 | } |
822 | 816 | ||
823 | /* | 817 | /* |
818 | * omap4iss_ipipeif_create_links() - IPIPEIF pads links creation | ||
819 | * @iss: Pointer to ISS device | ||
820 | * | ||
821 | * return negative error code or zero on success | ||
822 | */ | ||
823 | int omap4iss_ipipeif_create_links(struct iss_device *iss) | ||
824 | { | ||
825 | struct iss_ipipeif_device *ipipeif = &iss->ipipeif; | ||
826 | |||
827 | /* Connect the IPIPEIF subdev to the video node. */ | ||
828 | return media_create_pad_link(&ipipeif->subdev.entity, | ||
829 | IPIPEIF_PAD_SOURCE_ISIF_SF, | ||
830 | &ipipeif->video_out.video.entity, 0, 0); | ||
831 | } | ||
832 | |||
833 | /* | ||
824 | * omap4iss_ipipeif_cleanup - IPIPEIF module cleanup. | 834 | * omap4iss_ipipeif_cleanup - IPIPEIF module cleanup. |
825 | * @iss: Device pointer specific to the OMAP4 ISS. | 835 | * @iss: Device pointer specific to the OMAP4 ISS. |
826 | */ | 836 | */ |
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.h b/drivers/staging/media/omap4iss/iss_ipipeif.h index c6bd96d9656c..bad32b1d6ad8 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.h +++ b/drivers/staging/media/omap4iss/iss_ipipeif.h | |||
@@ -78,6 +78,7 @@ struct iss_ipipeif_device { | |||
78 | struct iss_device; | 78 | struct iss_device; |
79 | 79 | ||
80 | int omap4iss_ipipeif_init(struct iss_device *iss); | 80 | int omap4iss_ipipeif_init(struct iss_device *iss); |
81 | int omap4iss_ipipeif_create_links(struct iss_device *iss); | ||
81 | void omap4iss_ipipeif_cleanup(struct iss_device *iss); | 82 | void omap4iss_ipipeif_cleanup(struct iss_device *iss); |
82 | int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif, | 83 | int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif, |
83 | struct v4l2_device *vdev); | 84 | struct v4l2_device *vdev); |
diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 108961e05f53..f1d352c711d5 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c | |||
@@ -716,9 +716,14 @@ static int resizer_link_setup(struct media_entity *entity, | |||
716 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); | 716 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
717 | struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); | 717 | struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd); |
718 | struct iss_device *iss = to_iss_device(resizer); | 718 | struct iss_device *iss = to_iss_device(resizer); |
719 | unsigned int index = local->index; | ||
719 | 720 | ||
720 | switch (local->index | media_entity_type(remote->entity)) { | 721 | /* FIXME: this is actually a hack! */ |
721 | case RESIZER_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV: | 722 | if (is_media_entity_v4l2_subdev(remote->entity)) |
723 | index |= 2 << 16; | ||
724 | |||
725 | switch (index) { | ||
726 | case RESIZER_PAD_SINK | 2 << 16: | ||
722 | /* Read from IPIPE or IPIPEIF. */ | 727 | /* Read from IPIPE or IPIPEIF. */ |
723 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 728 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
724 | resizer->input = RESIZER_INPUT_NONE; | 729 | resizer->input = RESIZER_INPUT_NONE; |
@@ -735,7 +740,7 @@ static int resizer_link_setup(struct media_entity *entity, | |||
735 | 740 | ||
736 | break; | 741 | break; |
737 | 742 | ||
738 | case RESIZER_PAD_SOURCE_MEM | MEDIA_ENT_T_DEVNODE: | 743 | case RESIZER_PAD_SOURCE_MEM: |
739 | /* Write to memory */ | 744 | /* Write to memory */ |
740 | if (flags & MEDIA_LNK_FL_ENABLED) { | 745 | if (flags & MEDIA_LNK_FL_ENABLED) { |
741 | if (resizer->output & ~RESIZER_OUTPUT_MEMORY) | 746 | if (resizer->output & ~RESIZER_OUTPUT_MEMORY) |
@@ -785,7 +790,7 @@ static int resizer_init_entities(struct iss_resizer_device *resizer) | |||
785 | pads[RESIZER_PAD_SOURCE_MEM].flags = MEDIA_PAD_FL_SOURCE; | 790 | pads[RESIZER_PAD_SOURCE_MEM].flags = MEDIA_PAD_FL_SOURCE; |
786 | 791 | ||
787 | me->ops = &resizer_media_ops; | 792 | me->ops = &resizer_media_ops; |
788 | ret = media_entity_init(me, RESIZER_PADS_NUM, pads, 0); | 793 | ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); |
789 | if (ret < 0) | 794 | if (ret < 0) |
790 | return ret; | 795 | return ret; |
791 | 796 | ||
@@ -799,18 +804,7 @@ static int resizer_init_entities(struct iss_resizer_device *resizer) | |||
799 | resizer->video_out.bpl_zero_padding = 1; | 804 | resizer->video_out.bpl_zero_padding = 1; |
800 | resizer->video_out.bpl_max = 0x1ffe0; | 805 | resizer->video_out.bpl_max = 0x1ffe0; |
801 | 806 | ||
802 | ret = omap4iss_video_init(&resizer->video_out, "ISP resizer a"); | 807 | return omap4iss_video_init(&resizer->video_out, "ISP resizer a"); |
803 | if (ret < 0) | ||
804 | return ret; | ||
805 | |||
806 | /* Connect the RESIZER subdev to the video node. */ | ||
807 | ret = media_entity_create_link(&resizer->subdev.entity, | ||
808 | RESIZER_PAD_SOURCE_MEM, | ||
809 | &resizer->video_out.video.entity, 0, 0); | ||
810 | if (ret < 0) | ||
811 | return ret; | ||
812 | |||
813 | return 0; | ||
814 | } | 808 | } |
815 | 809 | ||
816 | void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer) | 810 | void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer) |
@@ -863,6 +857,22 @@ int omap4iss_resizer_init(struct iss_device *iss) | |||
863 | } | 857 | } |
864 | 858 | ||
865 | /* | 859 | /* |
860 | * omap4iss_resizer_create_links() - RESIZER pads links creation | ||
861 | * @iss: Pointer to ISS device | ||
862 | * | ||
863 | * return negative error code or zero on success | ||
864 | */ | ||
865 | int omap4iss_resizer_create_links(struct iss_device *iss) | ||
866 | { | ||
867 | struct iss_resizer_device *resizer = &iss->resizer; | ||
868 | |||
869 | /* Connect the RESIZER subdev to the video node. */ | ||
870 | return media_create_pad_link(&resizer->subdev.entity, | ||
871 | RESIZER_PAD_SOURCE_MEM, | ||
872 | &resizer->video_out.video.entity, 0, 0); | ||
873 | } | ||
874 | |||
875 | /* | ||
866 | * omap4iss_resizer_cleanup - RESIZER module cleanup. | 876 | * omap4iss_resizer_cleanup - RESIZER module cleanup. |
867 | * @iss: Device pointer specific to the OMAP4 ISS. | 877 | * @iss: Device pointer specific to the OMAP4 ISS. |
868 | */ | 878 | */ |
diff --git a/drivers/staging/media/omap4iss/iss_resizer.h b/drivers/staging/media/omap4iss/iss_resizer.h index 1e145abafc65..8b7c5fe9ffed 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.h +++ b/drivers/staging/media/omap4iss/iss_resizer.h | |||
@@ -61,6 +61,7 @@ struct iss_resizer_device { | |||
61 | struct iss_device; | 61 | struct iss_device; |
62 | 62 | ||
63 | int omap4iss_resizer_init(struct iss_device *iss); | 63 | int omap4iss_resizer_init(struct iss_device *iss); |
64 | int omap4iss_resizer_create_links(struct iss_device *iss); | ||
64 | void omap4iss_resizer_cleanup(struct iss_device *iss); | 65 | void omap4iss_resizer_cleanup(struct iss_device *iss); |
65 | int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer, | 66 | int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer, |
66 | struct v4l2_device *vdev); | 67 | struct v4l2_device *vdev); |
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index e9aeca08986f..058233a9de67 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c | |||
@@ -190,8 +190,7 @@ iss_video_remote_subdev(struct iss_video *video, u32 *pad) | |||
190 | 190 | ||
191 | remote = media_entity_remote_pad(&video->pad); | 191 | remote = media_entity_remote_pad(&video->pad); |
192 | 192 | ||
193 | if (!remote || | 193 | if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) |
194 | media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
195 | return NULL; | 194 | return NULL; |
196 | 195 | ||
197 | if (pad) | 196 | if (pad) |
@@ -206,17 +205,23 @@ iss_video_far_end(struct iss_video *video) | |||
206 | { | 205 | { |
207 | struct media_entity_graph graph; | 206 | struct media_entity_graph graph; |
208 | struct media_entity *entity = &video->video.entity; | 207 | struct media_entity *entity = &video->video.entity; |
209 | struct media_device *mdev = entity->parent; | 208 | struct media_device *mdev = entity->graph_obj.mdev; |
210 | struct iss_video *far_end = NULL; | 209 | struct iss_video *far_end = NULL; |
211 | 210 | ||
212 | mutex_lock(&mdev->graph_mutex); | 211 | mutex_lock(&mdev->graph_mutex); |
212 | |||
213 | if (media_entity_graph_walk_init(&graph, mdev)) { | ||
214 | mutex_unlock(&mdev->graph_mutex); | ||
215 | return NULL; | ||
216 | } | ||
217 | |||
213 | media_entity_graph_walk_start(&graph, entity); | 218 | media_entity_graph_walk_start(&graph, entity); |
214 | 219 | ||
215 | while ((entity = media_entity_graph_walk_next(&graph))) { | 220 | while ((entity = media_entity_graph_walk_next(&graph))) { |
216 | if (entity == &video->video.entity) | 221 | if (entity == &video->video.entity) |
217 | continue; | 222 | continue; |
218 | 223 | ||
219 | if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) | 224 | if (!is_media_entity_v4l2_io(entity)) |
220 | continue; | 225 | continue; |
221 | 226 | ||
222 | far_end = to_iss_video(media_entity_to_video_device(entity)); | 227 | far_end = to_iss_video(media_entity_to_video_device(entity)); |
@@ -227,6 +232,9 @@ iss_video_far_end(struct iss_video *video) | |||
227 | } | 232 | } |
228 | 233 | ||
229 | mutex_unlock(&mdev->graph_mutex); | 234 | mutex_unlock(&mdev->graph_mutex); |
235 | |||
236 | media_entity_graph_walk_cleanup(&graph); | ||
237 | |||
230 | return far_end; | 238 | return far_end; |
231 | } | 239 | } |
232 | 240 | ||
@@ -750,7 +758,7 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) | |||
750 | struct iss_video_fh *vfh = to_iss_video_fh(fh); | 758 | struct iss_video_fh *vfh = to_iss_video_fh(fh); |
751 | struct iss_video *video = video_drvdata(file); | 759 | struct iss_video *video = video_drvdata(file); |
752 | struct media_entity_graph graph; | 760 | struct media_entity_graph graph; |
753 | struct media_entity *entity; | 761 | struct media_entity *entity = &video->video.entity; |
754 | enum iss_pipeline_state state; | 762 | enum iss_pipeline_state state; |
755 | struct iss_pipeline *pipe; | 763 | struct iss_pipeline *pipe; |
756 | struct iss_video *far_end; | 764 | struct iss_video *far_end; |
@@ -765,24 +773,30 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) | |||
765 | /* Start streaming on the pipeline. No link touching an entity in the | 773 | /* Start streaming on the pipeline. No link touching an entity in the |
766 | * pipeline can be activated or deactivated once streaming is started. | 774 | * pipeline can be activated or deactivated once streaming is started. |
767 | */ | 775 | */ |
768 | pipe = video->video.entity.pipe | 776 | pipe = entity->pipe |
769 | ? to_iss_pipeline(&video->video.entity) : &video->pipe; | 777 | ? to_iss_pipeline(entity) : &video->pipe; |
770 | pipe->external = NULL; | 778 | pipe->external = NULL; |
771 | pipe->external_rate = 0; | 779 | pipe->external_rate = 0; |
772 | pipe->external_bpp = 0; | 780 | pipe->external_bpp = 0; |
773 | pipe->entities = 0; | 781 | |
782 | ret = media_entity_enum_init(&pipe->ent_enum, entity->graph_obj.mdev); | ||
783 | if (ret) | ||
784 | goto err_graph_walk_init; | ||
785 | |||
786 | ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev); | ||
787 | if (ret) | ||
788 | goto err_graph_walk_init; | ||
774 | 789 | ||
775 | if (video->iss->pdata->set_constraints) | 790 | if (video->iss->pdata->set_constraints) |
776 | video->iss->pdata->set_constraints(video->iss, true); | 791 | video->iss->pdata->set_constraints(video->iss, true); |
777 | 792 | ||
778 | ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe); | 793 | ret = media_entity_pipeline_start(entity, &pipe->pipe); |
779 | if (ret < 0) | 794 | if (ret < 0) |
780 | goto err_media_entity_pipeline_start; | 795 | goto err_media_entity_pipeline_start; |
781 | 796 | ||
782 | entity = &video->video.entity; | ||
783 | media_entity_graph_walk_start(&graph, entity); | 797 | media_entity_graph_walk_start(&graph, entity); |
784 | while ((entity = media_entity_graph_walk_next(&graph))) | 798 | while ((entity = media_entity_graph_walk_next(&graph))) |
785 | pipe->entities |= 1 << entity->id; | 799 | media_entity_enum_set(&pipe->ent_enum, entity); |
786 | 800 | ||
787 | /* Verify that the currently configured format matches the output of | 801 | /* Verify that the currently configured format matches the output of |
788 | * the connected subdev. | 802 | * the connected subdev. |
@@ -852,7 +866,10 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) | |||
852 | spin_unlock_irqrestore(&video->qlock, flags); | 866 | spin_unlock_irqrestore(&video->qlock, flags); |
853 | } | 867 | } |
854 | 868 | ||
869 | media_entity_graph_walk_cleanup(&graph); | ||
870 | |||
855 | mutex_unlock(&video->stream_lock); | 871 | mutex_unlock(&video->stream_lock); |
872 | |||
856 | return 0; | 873 | return 0; |
857 | 874 | ||
858 | err_omap4iss_set_stream: | 875 | err_omap4iss_set_stream: |
@@ -864,7 +881,13 @@ err_media_entity_pipeline_start: | |||
864 | video->iss->pdata->set_constraints(video->iss, false); | 881 | video->iss->pdata->set_constraints(video->iss, false); |
865 | video->queue = NULL; | 882 | video->queue = NULL; |
866 | 883 | ||
884 | media_entity_graph_walk_cleanup(&graph); | ||
885 | |||
886 | err_graph_walk_init: | ||
887 | media_entity_enum_cleanup(&pipe->ent_enum); | ||
888 | |||
867 | mutex_unlock(&video->stream_lock); | 889 | mutex_unlock(&video->stream_lock); |
890 | |||
868 | return ret; | 891 | return ret; |
869 | } | 892 | } |
870 | 893 | ||
@@ -902,6 +925,8 @@ iss_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) | |||
902 | vb2_streamoff(&vfh->queue, type); | 925 | vb2_streamoff(&vfh->queue, type); |
903 | video->queue = NULL; | 926 | video->queue = NULL; |
904 | 927 | ||
928 | media_entity_enum_cleanup(&pipe->ent_enum); | ||
929 | |||
905 | if (video->iss->pdata->set_constraints) | 930 | if (video->iss->pdata->set_constraints) |
906 | video->iss->pdata->set_constraints(video->iss, false); | 931 | video->iss->pdata->set_constraints(video->iss, false); |
907 | media_entity_pipeline_stop(&video->video.entity); | 932 | media_entity_pipeline_stop(&video->video.entity); |
@@ -984,7 +1009,13 @@ static int iss_video_open(struct file *file) | |||
984 | goto done; | 1009 | goto done; |
985 | } | 1010 | } |
986 | 1011 | ||
987 | ret = omap4iss_pipeline_pm_use(&video->video.entity, 1); | 1012 | ret = media_entity_graph_walk_init(&handle->graph, |
1013 | &video->iss->media_dev); | ||
1014 | if (ret) | ||
1015 | goto done; | ||
1016 | |||
1017 | ret = omap4iss_pipeline_pm_use(&video->video.entity, 1, | ||
1018 | &handle->graph); | ||
988 | if (ret < 0) { | 1019 | if (ret < 0) { |
989 | omap4iss_put(video->iss); | 1020 | omap4iss_put(video->iss); |
990 | goto done; | 1021 | goto done; |
@@ -1023,6 +1054,7 @@ static int iss_video_open(struct file *file) | |||
1023 | done: | 1054 | done: |
1024 | if (ret < 0) { | 1055 | if (ret < 0) { |
1025 | v4l2_fh_del(&handle->vfh); | 1056 | v4l2_fh_del(&handle->vfh); |
1057 | media_entity_graph_walk_cleanup(&handle->graph); | ||
1026 | kfree(handle); | 1058 | kfree(handle); |
1027 | } | 1059 | } |
1028 | 1060 | ||
@@ -1038,12 +1070,13 @@ static int iss_video_release(struct file *file) | |||
1038 | /* Disable streaming and free the buffers queue resources. */ | 1070 | /* Disable streaming and free the buffers queue resources. */ |
1039 | iss_video_streamoff(file, vfh, video->type); | 1071 | iss_video_streamoff(file, vfh, video->type); |
1040 | 1072 | ||
1041 | omap4iss_pipeline_pm_use(&video->video.entity, 0); | 1073 | omap4iss_pipeline_pm_use(&video->video.entity, 0, &handle->graph); |
1042 | 1074 | ||
1043 | /* Release the videobuf2 queue */ | 1075 | /* Release the videobuf2 queue */ |
1044 | vb2_queue_release(&handle->queue); | 1076 | vb2_queue_release(&handle->queue); |
1045 | 1077 | ||
1046 | /* Release the file handle. */ | 1078 | /* Release the file handle. */ |
1079 | media_entity_graph_walk_cleanup(&handle->graph); | ||
1047 | v4l2_fh_del(vfh); | 1080 | v4l2_fh_del(vfh); |
1048 | kfree(handle); | 1081 | kfree(handle); |
1049 | file->private_data = NULL; | 1082 | file->private_data = NULL; |
@@ -1102,7 +1135,7 @@ int omap4iss_video_init(struct iss_video *video, const char *name) | |||
1102 | return -EINVAL; | 1135 | return -EINVAL; |
1103 | } | 1136 | } |
1104 | 1137 | ||
1105 | ret = media_entity_init(&video->video.entity, 1, &video->pad, 0); | 1138 | ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); |
1106 | if (ret < 0) | 1139 | if (ret < 0) |
1107 | return ret; | 1140 | return ret; |
1108 | 1141 | ||
diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h index 41532eda1277..34588b7176ca 100644 --- a/drivers/staging/media/omap4iss/iss_video.h +++ b/drivers/staging/media/omap4iss/iss_video.h | |||
@@ -77,7 +77,7 @@ enum iss_pipeline_state { | |||
77 | 77 | ||
78 | /* | 78 | /* |
79 | * struct iss_pipeline - An OMAP4 ISS hardware pipeline | 79 | * struct iss_pipeline - An OMAP4 ISS hardware pipeline |
80 | * @entities: Bitmask of entities in the pipeline (indexed by entity ID) | 80 | * @ent_enum: Entities in the pipeline |
81 | * @error: A hardware error occurred during capture | 81 | * @error: A hardware error occurred during capture |
82 | */ | 82 | */ |
83 | struct iss_pipeline { | 83 | struct iss_pipeline { |
@@ -87,7 +87,7 @@ struct iss_pipeline { | |||
87 | enum iss_pipeline_stream_state stream_state; | 87 | enum iss_pipeline_stream_state stream_state; |
88 | struct iss_video *input; | 88 | struct iss_video *input; |
89 | struct iss_video *output; | 89 | struct iss_video *output; |
90 | unsigned int entities; | 90 | struct media_entity_enum ent_enum; |
91 | atomic_t frame_number; | 91 | atomic_t frame_number; |
92 | bool do_propagation; /* of frame number */ | 92 | bool do_propagation; /* of frame number */ |
93 | bool error; | 93 | bool error; |
@@ -183,6 +183,7 @@ struct iss_video_fh { | |||
183 | struct vb2_queue queue; | 183 | struct vb2_queue queue; |
184 | struct v4l2_format format; | 184 | struct v4l2_format format; |
185 | struct v4l2_fract timeperframe; | 185 | struct v4l2_fract timeperframe; |
186 | struct media_entity_graph graph; | ||
186 | }; | 187 | }; |
187 | 188 | ||
188 | #define to_iss_video_fh(fh) container_of(fh, struct iss_video_fh, vfh) | 189 | #define to_iss_video_fh(fh) container_of(fh, struct iss_video_fh, vfh) |
diff --git a/include/media/media-device.h b/include/media/media-device.h index 6e6db78f1ee2..d3855898c3fc 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h | |||
@@ -30,6 +30,238 @@ | |||
30 | #include <media/media-devnode.h> | 30 | #include <media/media-devnode.h> |
31 | #include <media/media-entity.h> | 31 | #include <media/media-entity.h> |
32 | 32 | ||
33 | /** | ||
34 | * DOC: Media Controller | ||
35 | * | ||
36 | * The media controller userspace API is documented in DocBook format in | ||
37 | * Documentation/DocBook/media/v4l/media-controller.xml. This document focus | ||
38 | * on the kernel-side implementation of the media framework. | ||
39 | * | ||
40 | * * Abstract media device model: | ||
41 | * | ||
42 | * Discovering a device internal topology, and configuring it at runtime, is one | ||
43 | * of the goals of the media framework. To achieve this, hardware devices are | ||
44 | * modelled as an oriented graph of building blocks called entities connected | ||
45 | * through pads. | ||
46 | * | ||
47 | * An entity is a basic media hardware building block. It can correspond to | ||
48 | * a large variety of logical blocks such as physical hardware devices | ||
49 | * (CMOS sensor for instance), logical hardware devices (a building block | ||
50 | * in a System-on-Chip image processing pipeline), DMA channels or physical | ||
51 | * connectors. | ||
52 | * | ||
53 | * A pad is a connection endpoint through which an entity can interact with | ||
54 | * other entities. Data (not restricted to video) produced by an entity | ||
55 | * flows from the entity's output to one or more entity inputs. Pads should | ||
56 | * not be confused with physical pins at chip boundaries. | ||
57 | * | ||
58 | * A link is a point-to-point oriented connection between two pads, either | ||
59 | * on the same entity or on different entities. Data flows from a source | ||
60 | * pad to a sink pad. | ||
61 | * | ||
62 | * | ||
63 | * * Media device: | ||
64 | * | ||
65 | * A media device is represented by a struct &media_device instance, defined in | ||
66 | * include/media/media-device.h. Allocation of the structure is handled by the | ||
67 | * media device driver, usually by embedding the &media_device instance in a | ||
68 | * larger driver-specific structure. | ||
69 | * | ||
70 | * Drivers register media device instances by calling | ||
71 | * __media_device_register() via the macro media_device_register() | ||
72 | * and unregistered by calling | ||
73 | * media_device_unregister(). | ||
74 | * | ||
75 | * * Entities, pads and links: | ||
76 | * | ||
77 | * - Entities | ||
78 | * | ||
79 | * Entities are represented by a struct &media_entity instance, defined in | ||
80 | * include/media/media-entity.h. The structure is usually embedded into a | ||
81 | * higher-level structure, such as a v4l2_subdev or video_device instance, | ||
82 | * although drivers can allocate entities directly. | ||
83 | * | ||
84 | * Drivers initialize entity pads by calling | ||
85 | * media_entity_pads_init(). | ||
86 | * | ||
87 | * Drivers register entities with a media device by calling | ||
88 | * media_device_register_entity() | ||
89 | * and unregistred by calling | ||
90 | * media_device_unregister_entity(). | ||
91 | * | ||
92 | * - Interfaces | ||
93 | * | ||
94 | * Interfaces are represented by a struct &media_interface instance, defined in | ||
95 | * include/media/media-entity.h. Currently, only one type of interface is | ||
96 | * defined: a device node. Such interfaces are represented by a struct | ||
97 | * &media_intf_devnode. | ||
98 | * | ||
99 | * Drivers initialize and create device node interfaces by calling | ||
100 | * media_devnode_create() | ||
101 | * and remove them by calling: | ||
102 | * media_devnode_remove(). | ||
103 | * | ||
104 | * - Pads | ||
105 | * | ||
106 | * Pads are represented by a struct &media_pad instance, defined in | ||
107 | * include/media/media-entity.h. Each entity stores its pads in a pads array | ||
108 | * managed by the entity driver. Drivers usually embed the array in a | ||
109 | * driver-specific structure. | ||
110 | * | ||
111 | * Pads are identified by their entity and their 0-based index in the pads | ||
112 | * array. | ||
113 | * Both information are stored in the &media_pad structure, making the | ||
114 | * &media_pad pointer the canonical way to store and pass link references. | ||
115 | * | ||
116 | * Pads have flags that describe the pad capabilities and state. | ||
117 | * | ||
118 | * %MEDIA_PAD_FL_SINK indicates that the pad supports sinking data. | ||
119 | * %MEDIA_PAD_FL_SOURCE indicates that the pad supports sourcing data. | ||
120 | * | ||
121 | * NOTE: One and only one of %MEDIA_PAD_FL_SINK and %MEDIA_PAD_FL_SOURCE must | ||
122 | * be set for each pad. | ||
123 | * | ||
124 | * - Links | ||
125 | * | ||
126 | * Links are represented by a struct &media_link instance, defined in | ||
127 | * include/media/media-entity.h. There are two types of links: | ||
128 | * | ||
129 | * 1. pad to pad links: | ||
130 | * | ||
131 | * Associate two entities via their PADs. Each entity has a list that points | ||
132 | * to all links originating at or targeting any of its pads. | ||
133 | * A given link is thus stored twice, once in the source entity and once in | ||
134 | * the target entity. | ||
135 | * | ||
136 | * Drivers create pad to pad links by calling: | ||
137 | * media_create_pad_link() and remove with media_entity_remove_links(). | ||
138 | * | ||
139 | * 2. interface to entity links: | ||
140 | * | ||
141 | * Associate one interface to a Link. | ||
142 | * | ||
143 | * Drivers create interface to entity links by calling: | ||
144 | * media_create_intf_link() and remove with media_remove_intf_links(). | ||
145 | * | ||
146 | * NOTE: | ||
147 | * | ||
148 | * Links can only be created after having both ends already created. | ||
149 | * | ||
150 | * Links have flags that describe the link capabilities and state. The | ||
151 | * valid values are described at media_create_pad_link() and | ||
152 | * media_create_intf_link(). | ||
153 | * | ||
154 | * Graph traversal: | ||
155 | * | ||
156 | * The media framework provides APIs to iterate over entities in a graph. | ||
157 | * | ||
158 | * To iterate over all entities belonging to a media device, drivers can use | ||
159 | * the media_device_for_each_entity macro, defined in | ||
160 | * include/media/media-device.h. | ||
161 | * | ||
162 | * struct media_entity *entity; | ||
163 | * | ||
164 | * media_device_for_each_entity(entity, mdev) { | ||
165 | * // entity will point to each entity in turn | ||
166 | * ... | ||
167 | * } | ||
168 | * | ||
169 | * Drivers might also need to iterate over all entities in a graph that can be | ||
170 | * reached only through enabled links starting at a given entity. The media | ||
171 | * framework provides a depth-first graph traversal API for that purpose. | ||
172 | * | ||
173 | * Note that graphs with cycles (whether directed or undirected) are *NOT* | ||
174 | * supported by the graph traversal API. To prevent infinite loops, the graph | ||
175 | * traversal code limits the maximum depth to MEDIA_ENTITY_ENUM_MAX_DEPTH, | ||
176 | * currently defined as 16. | ||
177 | * | ||
178 | * Drivers initiate a graph traversal by calling | ||
179 | * media_entity_graph_walk_start() | ||
180 | * | ||
181 | * The graph structure, provided by the caller, is initialized to start graph | ||
182 | * traversal at the given entity. | ||
183 | * | ||
184 | * Drivers can then retrieve the next entity by calling | ||
185 | * media_entity_graph_walk_next() | ||
186 | * | ||
187 | * When the graph traversal is complete the function will return NULL. | ||
188 | * | ||
189 | * Graph traversal can be interrupted at any moment. No cleanup function call | ||
190 | * is required and the graph structure can be freed normally. | ||
191 | * | ||
192 | * Helper functions can be used to find a link between two given pads, or a pad | ||
193 | * connected to another pad through an enabled link | ||
194 | * media_entity_find_link() and media_entity_remote_pad() | ||
195 | * | ||
196 | * Use count and power handling: | ||
197 | * | ||
198 | * Due to the wide differences between drivers regarding power management | ||
199 | * needs, the media controller does not implement power management. However, | ||
200 | * the &media_entity structure includes a use_count field that media drivers | ||
201 | * can use to track the number of users of every entity for power management | ||
202 | * needs. | ||
203 | * | ||
204 | * The &media_entity.@use_count field is owned by media drivers and must not be | ||
205 | * touched by entity drivers. Access to the field must be protected by the | ||
206 | * &media_device.@graph_mutex lock. | ||
207 | * | ||
208 | * Links setup: | ||
209 | * | ||
210 | * Link properties can be modified at runtime by calling | ||
211 | * media_entity_setup_link() | ||
212 | * | ||
213 | * Pipelines and media streams: | ||
214 | * | ||
215 | * When starting streaming, drivers must notify all entities in the pipeline to | ||
216 | * prevent link states from being modified during streaming by calling | ||
217 | * media_entity_pipeline_start(). | ||
218 | * | ||
219 | * The function will mark all entities connected to the given entity through | ||
220 | * enabled links, either directly or indirectly, as streaming. | ||
221 | * | ||
222 | * The &media_pipeline instance pointed to by the pipe argument will be stored | ||
223 | * in every entity in the pipeline. Drivers should embed the &media_pipeline | ||
224 | * structure in higher-level pipeline structures and can then access the | ||
225 | * pipeline through the &media_entity pipe field. | ||
226 | * | ||
227 | * Calls to media_entity_pipeline_start() can be nested. The pipeline pointer | ||
228 | * must be identical for all nested calls to the function. | ||
229 | * | ||
230 | * media_entity_pipeline_start() may return an error. In that case, it will | ||
231 | * clean up any of the changes it did by itself. | ||
232 | * | ||
233 | * When stopping the stream, drivers must notify the entities with | ||
234 | * media_entity_pipeline_stop(). | ||
235 | * | ||
236 | * If multiple calls to media_entity_pipeline_start() have been made the same | ||
237 | * number of media_entity_pipeline_stop() calls are required to stop streaming. | ||
238 | * The &media_entity pipe field is reset to NULL on the last nested stop call. | ||
239 | * | ||
240 | * Link configuration will fail with -%EBUSY by default if either end of the | ||
241 | * link is a streaming entity. Links that can be modified while streaming must | ||
242 | * be marked with the %MEDIA_LNK_FL_DYNAMIC flag. | ||
243 | * | ||
244 | * If other operations need to be disallowed on streaming entities (such as | ||
245 | * changing entities configuration parameters) drivers can explicitly check the | ||
246 | * media_entity stream_count field to find out if an entity is streaming. This | ||
247 | * operation must be done with the media_device graph_mutex held. | ||
248 | * | ||
249 | * Link validation: | ||
250 | * | ||
251 | * Link validation is performed by media_entity_pipeline_start() for any | ||
252 | * entity which has sink pads in the pipeline. The | ||
253 | * &media_entity.@link_validate() callback is used for that purpose. In | ||
254 | * @link_validate() callback, entity driver should check that the properties of | ||
255 | * the source pad of the connected entity and its own sink pad match. It is up | ||
256 | * to the type of the entity (and in the end, the properties of the hardware) | ||
257 | * what matching actually means. | ||
258 | * | ||
259 | * Subsystems should facilitate link validation by providing subsystem specific | ||
260 | * helper functions to provide easy access for commonly needed information, and | ||
261 | * in the end provide a way to use driver-specific callbacks. | ||
262 | */ | ||
263 | |||
264 | struct ida; | ||
33 | struct device; | 265 | struct device; |
34 | 266 | ||
35 | /** | 267 | /** |
@@ -41,8 +273,16 @@ struct device; | |||
41 | * @bus_info: Unique and stable device location identifier | 273 | * @bus_info: Unique and stable device location identifier |
42 | * @hw_revision: Hardware device revision | 274 | * @hw_revision: Hardware device revision |
43 | * @driver_version: Device driver version | 275 | * @driver_version: Device driver version |
44 | * @entity_id: ID of the next entity to be registered | 276 | * @topology_version: Monotonic counter for storing the version of the graph |
277 | * topology. Should be incremented each time the topology changes. | ||
278 | * @id: Unique ID used on the last registered graph object | ||
279 | * @entity_internal_idx: Unique internal entity ID used by the graph traversal | ||
280 | * algorithms | ||
281 | * @entity_internal_idx_max: Allocated internal entity indices | ||
45 | * @entities: List of registered entities | 282 | * @entities: List of registered entities |
283 | * @interfaces: List of registered interfaces | ||
284 | * @pads: List of registered pads | ||
285 | * @links: List of registered links | ||
46 | * @lock: Entities list lock | 286 | * @lock: Entities list lock |
47 | * @graph_mutex: Entities graph operation lock | 287 | * @graph_mutex: Entities graph operation lock |
48 | * @link_notify: Link state change notification callback | 288 | * @link_notify: Link state change notification callback |
@@ -68,10 +308,18 @@ struct media_device { | |||
68 | u32 hw_revision; | 308 | u32 hw_revision; |
69 | u32 driver_version; | 309 | u32 driver_version; |
70 | 310 | ||
71 | u32 entity_id; | 311 | u32 topology_version; |
312 | |||
313 | u32 id; | ||
314 | struct ida entity_internal_idx; | ||
315 | int entity_internal_idx_max; | ||
316 | |||
72 | struct list_head entities; | 317 | struct list_head entities; |
318 | struct list_head interfaces; | ||
319 | struct list_head pads; | ||
320 | struct list_head links; | ||
73 | 321 | ||
74 | /* Protects the entities list */ | 322 | /* Protects the graph objects creation/removal */ |
75 | spinlock_t lock; | 323 | spinlock_t lock; |
76 | /* Serializes graph operations. */ | 324 | /* Serializes graph operations. */ |
77 | struct mutex graph_mutex; | 325 | struct mutex graph_mutex; |
@@ -80,6 +328,8 @@ struct media_device { | |||
80 | unsigned int notification); | 328 | unsigned int notification); |
81 | }; | 329 | }; |
82 | 330 | ||
331 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
332 | |||
83 | /* Supported link_notify @notification values. */ | 333 | /* Supported link_notify @notification values. */ |
84 | #define MEDIA_DEV_NOTIFY_PRE_LINK_CH 0 | 334 | #define MEDIA_DEV_NOTIFY_PRE_LINK_CH 0 |
85 | #define MEDIA_DEV_NOTIFY_POST_LINK_CH 1 | 335 | #define MEDIA_DEV_NOTIFY_POST_LINK_CH 1 |
@@ -87,17 +337,228 @@ struct media_device { | |||
87 | /* media_devnode to media_device */ | 337 | /* media_devnode to media_device */ |
88 | #define to_media_device(node) container_of(node, struct media_device, devnode) | 338 | #define to_media_device(node) container_of(node, struct media_device, devnode) |
89 | 339 | ||
340 | /** | ||
341 | * media_entity_enum_init - Initialise an entity enumeration | ||
342 | * | ||
343 | * @ent_enum: Entity enumeration to be initialised | ||
344 | * @mdev: The related media device | ||
345 | * | ||
346 | * Returns zero on success or a negative error code. | ||
347 | */ | ||
348 | static inline __must_check int media_entity_enum_init( | ||
349 | struct media_entity_enum *ent_enum, struct media_device *mdev) | ||
350 | { | ||
351 | return __media_entity_enum_init(ent_enum, | ||
352 | mdev->entity_internal_idx_max + 1); | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * media_device_init() - Initializes a media device element | ||
357 | * | ||
358 | * @mdev: pointer to struct &media_device | ||
359 | * | ||
360 | * This function initializes the media device prior to its registration. | ||
361 | * The media device initialization and registration is split in two functions | ||
362 | * to avoid race conditions and make the media device available to user-space | ||
363 | * before the media graph has been completed. | ||
364 | * | ||
365 | * So drivers need to first initialize the media device, register any entity | ||
366 | * within the media device, create pad to pad links and then finally register | ||
367 | * the media device by calling media_device_register() as a final step. | ||
368 | */ | ||
369 | void media_device_init(struct media_device *mdev); | ||
370 | |||
371 | /** | ||
372 | * media_device_cleanup() - Cleanups a media device element | ||
373 | * | ||
374 | * @mdev: pointer to struct &media_device | ||
375 | * | ||
376 | * This function that will destroy the graph_mutex that is | ||
377 | * initialized in media_device_init(). | ||
378 | */ | ||
379 | void media_device_cleanup(struct media_device *mdev); | ||
380 | |||
381 | /** | ||
382 | * __media_device_register() - Registers a media device element | ||
383 | * | ||
384 | * @mdev: pointer to struct &media_device | ||
385 | * @owner: should be filled with %THIS_MODULE | ||
386 | * | ||
387 | * Users, should, instead, call the media_device_register() macro. | ||
388 | * | ||
389 | * The caller is responsible for initializing the media_device structure before | ||
390 | * registration. The following fields must be set: | ||
391 | * | ||
392 | * - dev must point to the parent device (usually a &pci_dev, &usb_interface or | ||
393 | * &platform_device instance). | ||
394 | * | ||
395 | * - model must be filled with the device model name as a NUL-terminated UTF-8 | ||
396 | * string. The device/model revision must not be stored in this field. | ||
397 | * | ||
398 | * The following fields are optional: | ||
399 | * | ||
400 | * - serial is a unique serial number stored as a NUL-terminated ASCII string. | ||
401 | * The field is big enough to store a GUID in text form. If the hardware | ||
402 | * doesn't provide a unique serial number this field must be left empty. | ||
403 | * | ||
404 | * - bus_info represents the location of the device in the system as a | ||
405 | * NUL-terminated ASCII string. For PCI/PCIe devices bus_info must be set to | ||
406 | * "PCI:" (or "PCIe:") followed by the value of pci_name(). For USB devices, | ||
407 | * the usb_make_path() function must be used. This field is used by | ||
408 | * applications to distinguish between otherwise identical devices that don't | ||
409 | * provide a serial number. | ||
410 | * | ||
411 | * - hw_revision is the hardware device revision in a driver-specific format. | ||
412 | * When possible the revision should be formatted with the KERNEL_VERSION | ||
413 | * macro. | ||
414 | * | ||
415 | * - driver_version is formatted with the KERNEL_VERSION macro. The version | ||
416 | * minor must be incremented when new features are added to the userspace API | ||
417 | * without breaking binary compatibility. The version major must be | ||
418 | * incremented when binary compatibility is broken. | ||
419 | * | ||
420 | * Notes: | ||
421 | * | ||
422 | * Upon successful registration a character device named media[0-9]+ is created. | ||
423 | * The device major and minor numbers are dynamic. The model name is exported as | ||
424 | * a sysfs attribute. | ||
425 | * | ||
426 | * Unregistering a media device that hasn't been registered is *NOT* safe. | ||
427 | * | ||
428 | * Return: returns zero on success or a negative error code. | ||
429 | */ | ||
90 | int __must_check __media_device_register(struct media_device *mdev, | 430 | int __must_check __media_device_register(struct media_device *mdev, |
91 | struct module *owner); | 431 | struct module *owner); |
92 | #define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE) | 432 | #define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE) |
433 | |||
434 | /** | ||
435 | * __media_device_unregister() - Unegisters a media device element | ||
436 | * | ||
437 | * @mdev: pointer to struct &media_device | ||
438 | * | ||
439 | * | ||
440 | * It is safe to call this function on an unregistered (but initialised) | ||
441 | * media device. | ||
442 | */ | ||
93 | void media_device_unregister(struct media_device *mdev); | 443 | void media_device_unregister(struct media_device *mdev); |
94 | 444 | ||
445 | /** | ||
446 | * media_device_register_entity() - registers a media entity inside a | ||
447 | * previously registered media device. | ||
448 | * | ||
449 | * @mdev: pointer to struct &media_device | ||
450 | * @entity: pointer to struct &media_entity to be registered | ||
451 | * | ||
452 | * Entities are identified by a unique positive integer ID. The media | ||
453 | * controller framework will such ID automatically. IDs are not guaranteed | ||
454 | * to be contiguous, and the ID number can change on newer Kernel versions. | ||
455 | * So, neither the driver nor userspace should hardcode ID numbers to refer | ||
456 | * to the entities, but, instead, use the framework to find the ID, when | ||
457 | * needed. | ||
458 | * | ||
459 | * The media_entity name, type and flags fields should be initialized before | ||
460 | * calling media_device_register_entity(). Entities embedded in higher-level | ||
461 | * standard structures can have some of those fields set by the higher-level | ||
462 | * framework. | ||
463 | * | ||
464 | * If the device has pads, media_entity_pads_init() should be called before | ||
465 | * this function. Otherwise, the &media_entity.@pad and &media_entity.@num_pads | ||
466 | * should be zeroed before calling this function. | ||
467 | * | ||
468 | * Entities have flags that describe the entity capabilities and state: | ||
469 | * | ||
470 | * %MEDIA_ENT_FL_DEFAULT indicates the default entity for a given type. | ||
471 | * This can be used to report the default audio and video devices or the | ||
472 | * default camera sensor. | ||
473 | * | ||
474 | * NOTE: Drivers should set the entity function before calling this function. | ||
475 | * Please notice that the values %MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN and | ||
476 | * %MEDIA_ENT_F_UNKNOWN should not be used by the drivers. | ||
477 | */ | ||
95 | int __must_check media_device_register_entity(struct media_device *mdev, | 478 | int __must_check media_device_register_entity(struct media_device *mdev, |
96 | struct media_entity *entity); | 479 | struct media_entity *entity); |
480 | |||
481 | /* | ||
482 | * media_device_unregister_entity() - unregisters a media entity. | ||
483 | * | ||
484 | * @entity: pointer to struct &media_entity to be unregistered | ||
485 | * | ||
486 | * All links associated with the entity and all PADs are automatically | ||
487 | * unregistered from the media_device when this function is called. | ||
488 | * | ||
489 | * Unregistering an entity will not change the IDs of the other entities and | ||
490 | * the previoully used ID will never be reused for a newly registered entities. | ||
491 | * | ||
492 | * When a media device is unregistered, all its entities are unregistered | ||
493 | * automatically. No manual entities unregistration is then required. | ||
494 | * | ||
495 | * Note: the media_entity instance itself must be freed explicitly by | ||
496 | * the driver if required. | ||
497 | */ | ||
97 | void media_device_unregister_entity(struct media_entity *entity); | 498 | void media_device_unregister_entity(struct media_entity *entity); |
98 | 499 | ||
500 | /** | ||
501 | * media_device_get_devres() - get media device as device resource | ||
502 | * creates if one doesn't exist | ||
503 | * | ||
504 | * @dev: pointer to struct &device. | ||
505 | * | ||
506 | * Sometimes, the media controller &media_device needs to be shared by more | ||
507 | * than one driver. This function adds support for that, by dynamically | ||
508 | * allocating the &media_device and allowing it to be obtained from the | ||
509 | * struct &device associated with the common device where all sub-device | ||
510 | * components belong. So, for example, on an USB device with multiple | ||
511 | * interfaces, each interface may be handled by a separate per-interface | ||
512 | * drivers. While each interface have its own &device, they all share a | ||
513 | * common &device associated with the hole USB device. | ||
514 | */ | ||
515 | struct media_device *media_device_get_devres(struct device *dev); | ||
516 | |||
517 | /** | ||
518 | * media_device_find_devres() - find media device as device resource | ||
519 | * | ||
520 | * @dev: pointer to struct &device. | ||
521 | */ | ||
522 | struct media_device *media_device_find_devres(struct device *dev); | ||
523 | |||
99 | /* Iterate over all entities. */ | 524 | /* Iterate over all entities. */ |
100 | #define media_device_for_each_entity(entity, mdev) \ | 525 | #define media_device_for_each_entity(entity, mdev) \ |
101 | list_for_each_entry(entity, &(mdev)->entities, list) | 526 | list_for_each_entry(entity, &(mdev)->entities, graph_obj.list) |
527 | |||
528 | /* Iterate over all interfaces. */ | ||
529 | #define media_device_for_each_intf(intf, mdev) \ | ||
530 | list_for_each_entry(intf, &(mdev)->interfaces, graph_obj.list) | ||
531 | |||
532 | /* Iterate over all pads. */ | ||
533 | #define media_device_for_each_pad(pad, mdev) \ | ||
534 | list_for_each_entry(pad, &(mdev)->pads, graph_obj.list) | ||
102 | 535 | ||
536 | /* Iterate over all links. */ | ||
537 | #define media_device_for_each_link(link, mdev) \ | ||
538 | list_for_each_entry(link, &(mdev)->links, graph_obj.list) | ||
539 | #else | ||
540 | static inline int media_device_register(struct media_device *mdev) | ||
541 | { | ||
542 | return 0; | ||
543 | } | ||
544 | static inline void media_device_unregister(struct media_device *mdev) | ||
545 | { | ||
546 | } | ||
547 | static inline int media_device_register_entity(struct media_device *mdev, | ||
548 | struct media_entity *entity) | ||
549 | { | ||
550 | return 0; | ||
551 | } | ||
552 | static inline void media_device_unregister_entity(struct media_entity *entity) | ||
553 | { | ||
554 | } | ||
555 | static inline struct media_device *media_device_get_devres(struct device *dev) | ||
556 | { | ||
557 | return NULL; | ||
558 | } | ||
559 | static inline struct media_device *media_device_find_devres(struct device *dev) | ||
560 | { | ||
561 | return NULL; | ||
562 | } | ||
563 | #endif /* CONFIG_MEDIA_CONTROLLER */ | ||
103 | #endif | 564 | #endif |
diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h index 17ddae32060d..fe42f08e72bd 100644 --- a/include/media/media-devnode.h +++ b/include/media/media-devnode.h | |||
@@ -40,6 +40,20 @@ | |||
40 | */ | 40 | */ |
41 | #define MEDIA_FLAG_REGISTERED 0 | 41 | #define MEDIA_FLAG_REGISTERED 0 |
42 | 42 | ||
43 | /** | ||
44 | * struct media_file_operations - Media device file operations | ||
45 | * | ||
46 | * @owner: should be filled with %THIS_MODULE | ||
47 | * @read: pointer to the function that implements read() syscall | ||
48 | * @write: pointer to the function that implements write() syscall | ||
49 | * @poll: pointer to the function that implements poll() syscall | ||
50 | * @ioctl: pointer to the function that implements ioctl() syscall | ||
51 | * @compat_ioctl: pointer to the function that will handle 32 bits userspace | ||
52 | * calls to the the ioctl() syscall on a Kernel compiled with 64 bits. | ||
53 | * @open: pointer to the function that implements open() syscall | ||
54 | * @release: pointer to the function that will release the resources allocated | ||
55 | * by the @open function. | ||
56 | */ | ||
43 | struct media_file_operations { | 57 | struct media_file_operations { |
44 | struct module *owner; | 58 | struct module *owner; |
45 | ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); | 59 | ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); |
@@ -53,7 +67,7 @@ struct media_file_operations { | |||
53 | 67 | ||
54 | /** | 68 | /** |
55 | * struct media_devnode - Media device node | 69 | * struct media_devnode - Media device node |
56 | * @fops: pointer to struct media_file_operations with media device ops | 70 | * @fops: pointer to struct &media_file_operations with media device ops |
57 | * @dev: struct device pointer for the media controller device | 71 | * @dev: struct device pointer for the media controller device |
58 | * @cdev: struct cdev pointer character device | 72 | * @cdev: struct cdev pointer character device |
59 | * @parent: parent device | 73 | * @parent: parent device |
@@ -86,15 +100,53 @@ struct media_devnode { | |||
86 | /* dev to media_devnode */ | 100 | /* dev to media_devnode */ |
87 | #define to_media_devnode(cd) container_of(cd, struct media_devnode, dev) | 101 | #define to_media_devnode(cd) container_of(cd, struct media_devnode, dev) |
88 | 102 | ||
103 | /** | ||
104 | * media_devnode_register - register a media device node | ||
105 | * | ||
106 | * @mdev: media device node structure we want to register | ||
107 | * @owner: should be filled with %THIS_MODULE | ||
108 | * | ||
109 | * The registration code assigns minor numbers and registers the new device node | ||
110 | * with the kernel. An error is returned if no free minor number can be found, | ||
111 | * or if the registration of the device node fails. | ||
112 | * | ||
113 | * Zero is returned on success. | ||
114 | * | ||
115 | * Note that if the media_devnode_register call fails, the release() callback of | ||
116 | * the media_devnode structure is *not* called, so the caller is responsible for | ||
117 | * freeing any data. | ||
118 | */ | ||
89 | int __must_check media_devnode_register(struct media_devnode *mdev, | 119 | int __must_check media_devnode_register(struct media_devnode *mdev, |
90 | struct module *owner); | 120 | struct module *owner); |
121 | |||
122 | /** | ||
123 | * media_devnode_unregister - unregister a media device node | ||
124 | * @mdev: the device node to unregister | ||
125 | * | ||
126 | * This unregisters the passed device. Future open calls will be met with | ||
127 | * errors. | ||
128 | * | ||
129 | * This function can safely be called if the device node has never been | ||
130 | * registered or has already been unregistered. | ||
131 | */ | ||
91 | void media_devnode_unregister(struct media_devnode *mdev); | 132 | void media_devnode_unregister(struct media_devnode *mdev); |
92 | 133 | ||
134 | /** | ||
135 | * media_devnode_data - returns a pointer to the &media_devnode | ||
136 | * | ||
137 | * @filp: pointer to struct &file | ||
138 | */ | ||
93 | static inline struct media_devnode *media_devnode_data(struct file *filp) | 139 | static inline struct media_devnode *media_devnode_data(struct file *filp) |
94 | { | 140 | { |
95 | return filp->private_data; | 141 | return filp->private_data; |
96 | } | 142 | } |
97 | 143 | ||
144 | /** | ||
145 | * media_devnode_is_registered - returns true if &media_devnode is registered; | ||
146 | * false otherwise. | ||
147 | * | ||
148 | * @mdev: pointer to struct &media_devnode. | ||
149 | */ | ||
98 | static inline int media_devnode_is_registered(struct media_devnode *mdev) | 150 | static inline int media_devnode_is_registered(struct media_devnode *mdev) |
99 | { | 151 | { |
100 | return test_bit(MEDIA_FLAG_REGISTERED, &mdev->flags); | 152 | return test_bit(MEDIA_FLAG_REGISTERED, &mdev->flags); |
diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 197f93799753..fe485d367985 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h | |||
@@ -23,25 +23,151 @@ | |||
23 | #ifndef _MEDIA_ENTITY_H | 23 | #ifndef _MEDIA_ENTITY_H |
24 | #define _MEDIA_ENTITY_H | 24 | #define _MEDIA_ENTITY_H |
25 | 25 | ||
26 | #include <linux/bitops.h> | 26 | #include <linux/bitmap.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/media.h> | 29 | #include <linux/media.h> |
30 | 30 | ||
31 | /* Enums used internally at the media controller to represent graphs */ | ||
32 | |||
33 | /** | ||
34 | * enum media_gobj_type - type of a graph object | ||
35 | * | ||
36 | * @MEDIA_GRAPH_ENTITY: Identify a media entity | ||
37 | * @MEDIA_GRAPH_PAD: Identify a media pad | ||
38 | * @MEDIA_GRAPH_LINK: Identify a media link | ||
39 | * @MEDIA_GRAPH_INTF_DEVNODE: Identify a media Kernel API interface via | ||
40 | * a device node | ||
41 | */ | ||
42 | enum media_gobj_type { | ||
43 | MEDIA_GRAPH_ENTITY, | ||
44 | MEDIA_GRAPH_PAD, | ||
45 | MEDIA_GRAPH_LINK, | ||
46 | MEDIA_GRAPH_INTF_DEVNODE, | ||
47 | }; | ||
48 | |||
49 | #define MEDIA_BITS_PER_TYPE 8 | ||
50 | #define MEDIA_BITS_PER_ID (32 - MEDIA_BITS_PER_TYPE) | ||
51 | #define MEDIA_ID_MASK GENMASK_ULL(MEDIA_BITS_PER_ID - 1, 0) | ||
52 | |||
53 | /* Structs to represent the objects that belong to a media graph */ | ||
54 | |||
55 | /** | ||
56 | * struct media_gobj - Define a graph object. | ||
57 | * | ||
58 | * @mdev: Pointer to the struct media_device that owns the object | ||
59 | * @id: Non-zero object ID identifier. The ID should be unique | ||
60 | * inside a media_device, as it is composed by | ||
61 | * %MEDIA_BITS_PER_TYPE to store the type plus | ||
62 | * %MEDIA_BITS_PER_ID to store the ID | ||
63 | * @list: List entry stored in one of the per-type mdev object lists | ||
64 | * | ||
65 | * All objects on the media graph should have this struct embedded | ||
66 | */ | ||
67 | struct media_gobj { | ||
68 | struct media_device *mdev; | ||
69 | u32 id; | ||
70 | struct list_head list; | ||
71 | }; | ||
72 | |||
73 | #define MEDIA_ENTITY_ENUM_MAX_DEPTH 16 | ||
74 | |||
75 | /** | ||
76 | * struct media_entity_enum - An enumeration of media entities. | ||
77 | * | ||
78 | * @bmap: Bit map in which each bit represents one entity at struct | ||
79 | * media_entity->internal_idx. | ||
80 | * @idx_max: Number of bits in bmap | ||
81 | */ | ||
82 | struct media_entity_enum { | ||
83 | unsigned long *bmap; | ||
84 | int idx_max; | ||
85 | }; | ||
86 | |||
87 | /** | ||
88 | * struct media_entity_graph - Media graph traversal state | ||
89 | * | ||
90 | * @stack: Graph traversal stack; the stack contains information | ||
91 | * on the path the media entities to be walked and the | ||
92 | * links through which they were reached. | ||
93 | * @ent_enum: Visited entities | ||
94 | * @top: The top of the stack | ||
95 | */ | ||
96 | struct media_entity_graph { | ||
97 | struct { | ||
98 | struct media_entity *entity; | ||
99 | struct list_head *link; | ||
100 | } stack[MEDIA_ENTITY_ENUM_MAX_DEPTH]; | ||
101 | |||
102 | struct media_entity_enum ent_enum; | ||
103 | int top; | ||
104 | }; | ||
105 | |||
106 | /* | ||
107 | * struct media_pipeline - Media pipeline related information | ||
108 | * | ||
109 | * @streaming_count: Streaming start count - streaming stop count | ||
110 | * @graph: Media graph walk during pipeline start / stop | ||
111 | */ | ||
31 | struct media_pipeline { | 112 | struct media_pipeline { |
113 | int streaming_count; | ||
114 | struct media_entity_graph graph; | ||
32 | }; | 115 | }; |
33 | 116 | ||
117 | /** | ||
118 | * struct media_link - A link object part of a media graph. | ||
119 | * | ||
120 | * @graph_obj: Embedded structure containing the media object common data | ||
121 | * @list: Linked list associated with an entity or an interface that | ||
122 | * owns the link. | ||
123 | * @gobj0: Part of a union. Used to get the pointer for the first | ||
124 | * graph_object of the link. | ||
125 | * @source: Part of a union. Used only if the first object (gobj0) is | ||
126 | * a pad. In that case, it represents the source pad. | ||
127 | * @intf: Part of a union. Used only if the first object (gobj0) is | ||
128 | * an interface. | ||
129 | * @gobj1: Part of a union. Used to get the pointer for the second | ||
130 | * graph_object of the link. | ||
131 | * @source: Part of a union. Used only if the second object (gobj1) is | ||
132 | * a pad. In that case, it represents the sink pad. | ||
133 | * @entity: Part of a union. Used only if the second object (gobj1) is | ||
134 | * an entity. | ||
135 | * @reverse: Pointer to the link for the reverse direction of a pad to pad | ||
136 | * link. | ||
137 | * @flags: Link flags, as defined in uapi/media.h (MEDIA_LNK_FL_*) | ||
138 | * @is_backlink: Indicate if the link is a backlink. | ||
139 | */ | ||
34 | struct media_link { | 140 | struct media_link { |
35 | struct media_pad *source; /* Source pad */ | 141 | struct media_gobj graph_obj; |
36 | struct media_pad *sink; /* Sink pad */ | 142 | struct list_head list; |
37 | struct media_link *reverse; /* Link in the reverse direction */ | 143 | union { |
38 | unsigned long flags; /* Link flags (MEDIA_LNK_FL_*) */ | 144 | struct media_gobj *gobj0; |
145 | struct media_pad *source; | ||
146 | struct media_interface *intf; | ||
147 | }; | ||
148 | union { | ||
149 | struct media_gobj *gobj1; | ||
150 | struct media_pad *sink; | ||
151 | struct media_entity *entity; | ||
152 | }; | ||
153 | struct media_link *reverse; | ||
154 | unsigned long flags; | ||
155 | bool is_backlink; | ||
39 | }; | 156 | }; |
40 | 157 | ||
158 | /** | ||
159 | * struct media_pad - A media pad graph object. | ||
160 | * | ||
161 | * @graph_obj: Embedded structure containing the media object common data | ||
162 | * @entity: Entity this pad belongs to | ||
163 | * @index: Pad index in the entity pads array, numbered from 0 to n | ||
164 | * @flags: Pad flags, as defined in uapi/media.h (MEDIA_PAD_FL_*) | ||
165 | */ | ||
41 | struct media_pad { | 166 | struct media_pad { |
42 | struct media_entity *entity; /* Entity this pad belongs to */ | 167 | struct media_gobj graph_obj; /* must be first field in struct */ |
43 | u16 index; /* Pad index in the entity pads array */ | 168 | struct media_entity *entity; |
44 | unsigned long flags; /* Pad flags (MEDIA_PAD_FL_*) */ | 169 | u16 index; |
170 | unsigned long flags; | ||
45 | }; | 171 | }; |
46 | 172 | ||
47 | /** | 173 | /** |
@@ -60,105 +186,763 @@ struct media_entity_operations { | |||
60 | int (*link_validate)(struct media_link *link); | 186 | int (*link_validate)(struct media_link *link); |
61 | }; | 187 | }; |
62 | 188 | ||
189 | /** | ||
190 | * struct media_entity - A media entity graph object. | ||
191 | * | ||
192 | * @graph_obj: Embedded structure containing the media object common data. | ||
193 | * @name: Entity name. | ||
194 | * @function: Entity main function, as defined in uapi/media.h | ||
195 | * (MEDIA_ENT_F_*) | ||
196 | * @flags: Entity flags, as defined in uapi/media.h (MEDIA_ENT_FL_*) | ||
197 | * @num_pads: Number of sink and source pads. | ||
198 | * @num_links: Total number of links, forward and back, enabled and disabled. | ||
199 | * @num_backlinks: Number of backlinks | ||
200 | * @internal_idx: An unique internal entity specific number. The numbers are | ||
201 | * re-used if entities are unregistered or registered again. | ||
202 | * @pads: Pads array with the size defined by @num_pads. | ||
203 | * @links: List of data links. | ||
204 | * @ops: Entity operations. | ||
205 | * @stream_count: Stream count for the entity. | ||
206 | * @use_count: Use count for the entity. | ||
207 | * @pipe: Pipeline this entity belongs to. | ||
208 | * @info: Union with devnode information. Kept just for backward | ||
209 | * compatibility. | ||
210 | * @major: Devnode major number (zero if not applicable). Kept just | ||
211 | * for backward compatibility. | ||
212 | * @minor: Devnode minor number (zero if not applicable). Kept just | ||
213 | * for backward compatibility. | ||
214 | * | ||
215 | * NOTE: @stream_count and @use_count reference counts must never be | ||
216 | * negative, but are signed integers on purpose: a simple WARN_ON(<0) check | ||
217 | * can be used to detect reference count bugs that would make them negative. | ||
218 | */ | ||
63 | struct media_entity { | 219 | struct media_entity { |
64 | struct list_head list; | 220 | struct media_gobj graph_obj; /* must be first field in struct */ |
65 | struct media_device *parent; /* Media device this entity belongs to*/ | 221 | const char *name; |
66 | u32 id; /* Entity ID, unique in the parent media | 222 | u32 function; |
67 | * device context */ | 223 | unsigned long flags; |
68 | const char *name; /* Entity name */ | 224 | |
69 | u32 type; /* Entity type (MEDIA_ENT_T_*) */ | 225 | u16 num_pads; |
70 | u32 revision; /* Entity revision, driver specific */ | 226 | u16 num_links; |
71 | unsigned long flags; /* Entity flags (MEDIA_ENT_FL_*) */ | 227 | u16 num_backlinks; |
72 | u32 group_id; /* Entity group ID */ | 228 | int internal_idx; |
73 | 229 | ||
74 | u16 num_pads; /* Number of sink and source pads */ | 230 | struct media_pad *pads; |
75 | u16 num_links; /* Number of existing links, both | 231 | struct list_head links; |
76 | * enabled and disabled */ | 232 | |
77 | u16 num_backlinks; /* Number of backlinks */ | 233 | const struct media_entity_operations *ops; |
78 | u16 max_links; /* Maximum number of links */ | ||
79 | |||
80 | struct media_pad *pads; /* Pads array (num_pads elements) */ | ||
81 | struct media_link *links; /* Links array (max_links elements)*/ | ||
82 | |||
83 | const struct media_entity_operations *ops; /* Entity operations */ | ||
84 | 234 | ||
85 | /* Reference counts must never be negative, but are signed integers on | 235 | /* Reference counts must never be negative, but are signed integers on |
86 | * purpose: a simple WARN_ON(<0) check can be used to detect reference | 236 | * purpose: a simple WARN_ON(<0) check can be used to detect reference |
87 | * count bugs that would make them negative. | 237 | * count bugs that would make them negative. |
88 | */ | 238 | */ |
89 | int stream_count; /* Stream count for the entity. */ | 239 | int stream_count; |
90 | int use_count; /* Use count for the entity. */ | 240 | int use_count; |
91 | 241 | ||
92 | struct media_pipeline *pipe; /* Pipeline this entity belongs to. */ | 242 | struct media_pipeline *pipe; |
93 | 243 | ||
94 | union { | 244 | union { |
95 | /* Node specifications */ | ||
96 | struct { | 245 | struct { |
97 | u32 major; | 246 | u32 major; |
98 | u32 minor; | 247 | u32 minor; |
99 | } dev; | 248 | } dev; |
100 | |||
101 | /* Sub-device specifications */ | ||
102 | /* Nothing needed yet */ | ||
103 | } info; | 249 | } info; |
104 | }; | 250 | }; |
105 | 251 | ||
106 | static inline u32 media_entity_type(struct media_entity *entity) | 252 | /** |
253 | * struct media_interface - A media interface graph object. | ||
254 | * | ||
255 | * @graph_obj: embedded graph object | ||
256 | * @links: List of links pointing to graph entities | ||
257 | * @type: Type of the interface as defined in the | ||
258 | * uapi/media/media.h header, e. g. | ||
259 | * MEDIA_INTF_T_* | ||
260 | * @flags: Interface flags as defined in uapi/media/media.h | ||
261 | */ | ||
262 | struct media_interface { | ||
263 | struct media_gobj graph_obj; | ||
264 | struct list_head links; | ||
265 | u32 type; | ||
266 | u32 flags; | ||
267 | }; | ||
268 | |||
269 | /** | ||
270 | * struct media_intf_devnode - A media interface via a device node. | ||
271 | * | ||
272 | * @intf: embedded interface object | ||
273 | * @major: Major number of a device node | ||
274 | * @minor: Minor number of a device node | ||
275 | */ | ||
276 | struct media_intf_devnode { | ||
277 | struct media_interface intf; | ||
278 | |||
279 | /* Should match the fields at media_v2_intf_devnode */ | ||
280 | u32 major; | ||
281 | u32 minor; | ||
282 | }; | ||
283 | |||
284 | /** | ||
285 | * media_entity_id() - return the media entity graph object id | ||
286 | * | ||
287 | * @entity: pointer to entity | ||
288 | */ | ||
289 | static inline u32 media_entity_id(struct media_entity *entity) | ||
107 | { | 290 | { |
108 | return entity->type & MEDIA_ENT_TYPE_MASK; | 291 | return entity->graph_obj.id; |
109 | } | 292 | } |
110 | 293 | ||
111 | static inline u32 media_entity_subtype(struct media_entity *entity) | 294 | /** |
295 | * media_type() - return the media object type | ||
296 | * | ||
297 | * @gobj: pointer to the media graph object | ||
298 | */ | ||
299 | static inline enum media_gobj_type media_type(struct media_gobj *gobj) | ||
112 | { | 300 | { |
113 | return entity->type & MEDIA_ENT_SUBTYPE_MASK; | 301 | return gobj->id >> MEDIA_BITS_PER_ID; |
114 | } | 302 | } |
115 | 303 | ||
116 | #define MEDIA_ENTITY_ENUM_MAX_DEPTH 16 | 304 | /** |
117 | #define MEDIA_ENTITY_ENUM_MAX_ID 64 | 305 | * media_id() - return the media object ID |
306 | * | ||
307 | * @gobj: pointer to the media graph object | ||
308 | */ | ||
309 | static inline u32 media_id(struct media_gobj *gobj) | ||
310 | { | ||
311 | return gobj->id & MEDIA_ID_MASK; | ||
312 | } | ||
118 | 313 | ||
119 | /* | 314 | /** |
120 | * The number of pads can't be bigger than the number of entities, | 315 | * media_gobj_gen_id() - encapsulates type and ID on at the object ID |
121 | * as the worse-case scenario is to have one entity linked up to | 316 | * |
122 | * MEDIA_ENTITY_ENUM_MAX_ID - 1 entities. | 317 | * @type: object type as define at enum &media_gobj_type. |
318 | * @local_id: next ID, from struct &media_device.@id. | ||
123 | */ | 319 | */ |
124 | #define MEDIA_ENTITY_MAX_PADS (MEDIA_ENTITY_ENUM_MAX_ID - 1) | 320 | static inline u32 media_gobj_gen_id(enum media_gobj_type type, u64 local_id) |
321 | { | ||
322 | u32 id; | ||
125 | 323 | ||
126 | struct media_entity_graph { | 324 | id = type << MEDIA_BITS_PER_ID; |
127 | struct { | 325 | id |= local_id & MEDIA_ID_MASK; |
128 | struct media_entity *entity; | ||
129 | int link; | ||
130 | } stack[MEDIA_ENTITY_ENUM_MAX_DEPTH]; | ||
131 | 326 | ||
132 | DECLARE_BITMAP(entities, MEDIA_ENTITY_ENUM_MAX_ID); | 327 | return id; |
133 | int top; | 328 | } |
134 | }; | 329 | |
330 | /** | ||
331 | * is_media_entity_v4l2_io() - identify if the entity main function | ||
332 | * is a V4L2 I/O | ||
333 | * | ||
334 | * @entity: pointer to entity | ||
335 | * | ||
336 | * Return: true if the entity main function is one of the V4L2 I/O types | ||
337 | * (video, VBI or SDR radio); false otherwise. | ||
338 | */ | ||
339 | static inline bool is_media_entity_v4l2_io(struct media_entity *entity) | ||
340 | { | ||
341 | if (!entity) | ||
342 | return false; | ||
343 | |||
344 | switch (entity->function) { | ||
345 | case MEDIA_ENT_F_IO_V4L: | ||
346 | case MEDIA_ENT_F_IO_VBI: | ||
347 | case MEDIA_ENT_F_IO_SWRADIO: | ||
348 | return true; | ||
349 | default: | ||
350 | return false; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * is_media_entity_v4l2_subdev - return true if the entity main function is | ||
356 | * associated with the V4L2 API subdev usage | ||
357 | * | ||
358 | * @entity: pointer to entity | ||
359 | * | ||
360 | * This is an ancillary function used by subdev-based V4L2 drivers. | ||
361 | * It checks if the entity function is one of functions used by a V4L2 subdev, | ||
362 | * e. g. camera-relatef functions, analog TV decoder, TV tuner, V4L2 DSPs. | ||
363 | */ | ||
364 | static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) | ||
365 | { | ||
366 | if (!entity) | ||
367 | return false; | ||
368 | |||
369 | switch (entity->function) { | ||
370 | case MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN: | ||
371 | case MEDIA_ENT_F_CAM_SENSOR: | ||
372 | case MEDIA_ENT_F_FLASH: | ||
373 | case MEDIA_ENT_F_LENS: | ||
374 | case MEDIA_ENT_F_ATV_DECODER: | ||
375 | case MEDIA_ENT_F_TUNER: | ||
376 | return true; | ||
377 | |||
378 | default: | ||
379 | return false; | ||
380 | } | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * __media_entity_enum_init - Initialise an entity enumeration | ||
385 | * | ||
386 | * @ent_enum: Entity enumeration to be initialised | ||
387 | * @idx_max: Maximum number of entities in the enumeration | ||
388 | * | ||
389 | * Return: Returns zero on success or a negative error code. | ||
390 | */ | ||
391 | __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum, | ||
392 | int idx_max); | ||
393 | |||
394 | /** | ||
395 | * media_entity_enum_cleanup - Release resources of an entity enumeration | ||
396 | * | ||
397 | * @ent_enum: Entity enumeration to be released | ||
398 | */ | ||
399 | void media_entity_enum_cleanup(struct media_entity_enum *ent_enum); | ||
400 | |||
401 | /** | ||
402 | * media_entity_enum_zero - Clear the entire enum | ||
403 | * | ||
404 | * @ent_enum: Entity enumeration to be cleared | ||
405 | */ | ||
406 | static inline void media_entity_enum_zero(struct media_entity_enum *ent_enum) | ||
407 | { | ||
408 | bitmap_zero(ent_enum->bmap, ent_enum->idx_max); | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * media_entity_enum_set - Mark a single entity in the enum | ||
413 | * | ||
414 | * @ent_enum: Entity enumeration | ||
415 | * @entity: Entity to be marked | ||
416 | */ | ||
417 | static inline void media_entity_enum_set(struct media_entity_enum *ent_enum, | ||
418 | struct media_entity *entity) | ||
419 | { | ||
420 | if (WARN_ON(entity->internal_idx >= ent_enum->idx_max)) | ||
421 | return; | ||
422 | |||
423 | __set_bit(entity->internal_idx, ent_enum->bmap); | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * media_entity_enum_clear - Unmark a single entity in the enum | ||
428 | * | ||
429 | * @ent_enum: Entity enumeration | ||
430 | * @entity: Entity to be unmarked | ||
431 | */ | ||
432 | static inline void media_entity_enum_clear(struct media_entity_enum *ent_enum, | ||
433 | struct media_entity *entity) | ||
434 | { | ||
435 | if (WARN_ON(entity->internal_idx >= ent_enum->idx_max)) | ||
436 | return; | ||
135 | 437 | ||
136 | int media_entity_init(struct media_entity *entity, u16 num_pads, | 438 | __clear_bit(entity->internal_idx, ent_enum->bmap); |
137 | struct media_pad *pads, u16 extra_links); | 439 | } |
138 | void media_entity_cleanup(struct media_entity *entity); | 440 | |
441 | /** | ||
442 | * media_entity_enum_test - Test whether the entity is marked | ||
443 | * | ||
444 | * @ent_enum: Entity enumeration | ||
445 | * @entity: Entity to be tested | ||
446 | * | ||
447 | * Returns true if the entity was marked. | ||
448 | */ | ||
449 | static inline bool media_entity_enum_test(struct media_entity_enum *ent_enum, | ||
450 | struct media_entity *entity) | ||
451 | { | ||
452 | if (WARN_ON(entity->internal_idx >= ent_enum->idx_max)) | ||
453 | return true; | ||
454 | |||
455 | return test_bit(entity->internal_idx, ent_enum->bmap); | ||
456 | } | ||
457 | |||
458 | /** | ||
459 | * media_entity_enum_test - Test whether the entity is marked, and mark it | ||
460 | * | ||
461 | * @ent_enum: Entity enumeration | ||
462 | * @entity: Entity to be tested | ||
463 | * | ||
464 | * Returns true if the entity was marked, and mark it before doing so. | ||
465 | */ | ||
466 | static inline bool | ||
467 | media_entity_enum_test_and_set(struct media_entity_enum *ent_enum, | ||
468 | struct media_entity *entity) | ||
469 | { | ||
470 | if (WARN_ON(entity->internal_idx >= ent_enum->idx_max)) | ||
471 | return true; | ||
472 | |||
473 | return __test_and_set_bit(entity->internal_idx, ent_enum->bmap); | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * media_entity_enum_empty - Test whether the entire enum is empty | ||
478 | * | ||
479 | * @ent_enum: Entity enumeration | ||
480 | * | ||
481 | * Returns true if the entity was marked. | ||
482 | */ | ||
483 | static inline bool media_entity_enum_empty(struct media_entity_enum *ent_enum) | ||
484 | { | ||
485 | return bitmap_empty(ent_enum->bmap, ent_enum->idx_max); | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * media_entity_enum_intersects - Test whether two enums intersect | ||
490 | * | ||
491 | * @ent_enum1: First entity enumeration | ||
492 | * @ent_enum2: Second entity enumeration | ||
493 | * | ||
494 | * Returns true if entity enumerations e and f intersect, otherwise false. | ||
495 | */ | ||
496 | static inline bool media_entity_enum_intersects( | ||
497 | struct media_entity_enum *ent_enum1, | ||
498 | struct media_entity_enum *ent_enum2) | ||
499 | { | ||
500 | WARN_ON(ent_enum1->idx_max != ent_enum2->idx_max); | ||
501 | |||
502 | return bitmap_intersects(ent_enum1->bmap, ent_enum2->bmap, | ||
503 | min(ent_enum1->idx_max, ent_enum2->idx_max)); | ||
504 | } | ||
505 | |||
506 | #define gobj_to_entity(gobj) \ | ||
507 | container_of(gobj, struct media_entity, graph_obj) | ||
508 | |||
509 | #define gobj_to_pad(gobj) \ | ||
510 | container_of(gobj, struct media_pad, graph_obj) | ||
511 | |||
512 | #define gobj_to_link(gobj) \ | ||
513 | container_of(gobj, struct media_link, graph_obj) | ||
514 | |||
515 | #define gobj_to_link(gobj) \ | ||
516 | container_of(gobj, struct media_link, graph_obj) | ||
517 | |||
518 | #define gobj_to_pad(gobj) \ | ||
519 | container_of(gobj, struct media_pad, graph_obj) | ||
520 | |||
521 | #define gobj_to_intf(gobj) \ | ||
522 | container_of(gobj, struct media_interface, graph_obj) | ||
523 | |||
524 | #define intf_to_devnode(intf) \ | ||
525 | container_of(intf, struct media_intf_devnode, intf) | ||
526 | |||
527 | /** | ||
528 | * media_gobj_create - Initialize a graph object | ||
529 | * | ||
530 | * @mdev: Pointer to the media_device that contains the object | ||
531 | * @type: Type of the object | ||
532 | * @gobj: Pointer to the graph object | ||
533 | * | ||
534 | * This routine initializes the embedded struct media_gobj inside a | ||
535 | * media graph object. It is called automatically if media_*_create() | ||
536 | * calls are used. However, if the object (entity, link, pad, interface) | ||
537 | * is embedded on some other object, this function should be called before | ||
538 | * registering the object at the media controller. | ||
539 | */ | ||
540 | void media_gobj_create(struct media_device *mdev, | ||
541 | enum media_gobj_type type, | ||
542 | struct media_gobj *gobj); | ||
543 | |||
544 | /** | ||
545 | * media_gobj_destroy - Stop using a graph object on a media device | ||
546 | * | ||
547 | * @gobj: Pointer to the graph object | ||
548 | * | ||
549 | * This should be called by all routines like media_device_unregister() | ||
550 | * that remove/destroy media graph objects. | ||
551 | */ | ||
552 | void media_gobj_destroy(struct media_gobj *gobj); | ||
553 | |||
554 | /** | ||
555 | * media_entity_pads_init() - Initialize the entity pads | ||
556 | * | ||
557 | * @entity: entity where the pads belong | ||
558 | * @num_pads: total number of sink and source pads | ||
559 | * @pads: Array of @num_pads pads. | ||
560 | * | ||
561 | * The pads array is managed by the entity driver and passed to | ||
562 | * media_entity_pads_init() where its pointer will be stored in the entity | ||
563 | * structure. | ||
564 | * | ||
565 | * If no pads are needed, drivers could either directly fill | ||
566 | * &media_entity->@num_pads with 0 and &media_entity->@pads with NULL or call | ||
567 | * this function that will do the same. | ||
568 | * | ||
569 | * As the number of pads is known in advance, the pads array is not allocated | ||
570 | * dynamically but is managed by the entity driver. Most drivers will embed the | ||
571 | * pads array in a driver-specific structure, avoiding dynamic allocation. | ||
572 | * | ||
573 | * Drivers must set the direction of every pad in the pads array before calling | ||
574 | * media_entity_pads_init(). The function will initialize the other pads fields. | ||
575 | */ | ||
576 | int media_entity_pads_init(struct media_entity *entity, u16 num_pads, | ||
577 | struct media_pad *pads); | ||
578 | |||
579 | /** | ||
580 | * media_entity_cleanup() - free resources associated with an entity | ||
581 | * | ||
582 | * @entity: entity where the pads belong | ||
583 | * | ||
584 | * This function must be called during the cleanup phase after unregistering | ||
585 | * the entity (currently, it does nothing). | ||
586 | */ | ||
587 | static inline void media_entity_cleanup(struct media_entity *entity) {}; | ||
588 | |||
589 | /** | ||
590 | * media_create_pad_link() - creates a link between two entities. | ||
591 | * | ||
592 | * @source: pointer to &media_entity of the source pad. | ||
593 | * @source_pad: number of the source pad in the pads array | ||
594 | * @sink: pointer to &media_entity of the sink pad. | ||
595 | * @sink_pad: number of the sink pad in the pads array. | ||
596 | * @flags: Link flags, as defined in include/uapi/linux/media.h. | ||
597 | * | ||
598 | * Valid values for flags: | ||
599 | * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be | ||
600 | * used to transfer media data. When two or more links target a sink pad, | ||
601 | * only one of them can be enabled at a time. | ||
602 | * | ||
603 | * A %MEDIA_LNK_FL_IMMUTABLE flag indicates that the link enabled state can't | ||
604 | * be modified at runtime. If %MEDIA_LNK_FL_IMMUTABLE is set, then | ||
605 | * %MEDIA_LNK_FL_ENABLED must also be set since an immutable link is | ||
606 | * always enabled. | ||
607 | * | ||
608 | * NOTE: | ||
609 | * | ||
610 | * Before calling this function, media_entity_pads_init() and | ||
611 | * media_device_register_entity() should be called previously for both ends. | ||
612 | */ | ||
613 | __must_check int media_create_pad_link(struct media_entity *source, | ||
614 | u16 source_pad, struct media_entity *sink, | ||
615 | u16 sink_pad, u32 flags); | ||
616 | |||
617 | /** | ||
618 | * media_create_pad_links() - creates a link between two entities. | ||
619 | * | ||
620 | * @mdev: Pointer to the media_device that contains the object | ||
621 | * @source_function: Function of the source entities. Used only if @source is | ||
622 | * NULL. | ||
623 | * @source: pointer to &media_entity of the source pad. If NULL, it will use | ||
624 | * all entities that matches the @sink_function. | ||
625 | * @source_pad: number of the source pad in the pads array | ||
626 | * @sink_function: Function of the sink entities. Used only if @sink is NULL. | ||
627 | * @sink: pointer to &media_entity of the sink pad. If NULL, it will use | ||
628 | * all entities that matches the @sink_function. | ||
629 | * @sink_pad: number of the sink pad in the pads array. | ||
630 | * @flags: Link flags, as defined in include/uapi/linux/media.h. | ||
631 | * @allow_both_undefined: if true, then both @source and @sink can be NULL. | ||
632 | * In such case, it will create a crossbar between all entities that | ||
633 | * matches @source_function to all entities that matches @sink_function. | ||
634 | * If false, it will return 0 and won't create any link if both @source | ||
635 | * and @sink are NULL. | ||
636 | * | ||
637 | * Valid values for flags: | ||
638 | * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be | ||
639 | * used to transfer media data. If multiple links are created and this | ||
640 | * flag is passed as an argument, only the first created link will have | ||
641 | * this flag. | ||
642 | * | ||
643 | * A %MEDIA_LNK_FL_IMMUTABLE flag indicates that the link enabled state can't | ||
644 | * be modified at runtime. If %MEDIA_LNK_FL_IMMUTABLE is set, then | ||
645 | * %MEDIA_LNK_FL_ENABLED must also be set since an immutable link is | ||
646 | * always enabled. | ||
647 | * | ||
648 | * It is common for some devices to have multiple source and/or sink entities | ||
649 | * of the same type that should be linked. While media_create_pad_link() | ||
650 | * creates link by link, this function is meant to allow 1:n, n:1 and even | ||
651 | * cross-bar (n:n) links. | ||
652 | * | ||
653 | * NOTE: Before calling this function, media_entity_pads_init() and | ||
654 | * media_device_register_entity() should be called previously for the entities | ||
655 | * to be linked. | ||
656 | */ | ||
657 | int media_create_pad_links(const struct media_device *mdev, | ||
658 | const u32 source_function, | ||
659 | struct media_entity *source, | ||
660 | const u16 source_pad, | ||
661 | const u32 sink_function, | ||
662 | struct media_entity *sink, | ||
663 | const u16 sink_pad, | ||
664 | u32 flags, | ||
665 | const bool allow_both_undefined); | ||
139 | 666 | ||
140 | int media_entity_create_link(struct media_entity *source, u16 source_pad, | ||
141 | struct media_entity *sink, u16 sink_pad, u32 flags); | ||
142 | void __media_entity_remove_links(struct media_entity *entity); | 667 | void __media_entity_remove_links(struct media_entity *entity); |
668 | |||
669 | /** | ||
670 | * media_entity_remove_links() - remove all links associated with an entity | ||
671 | * | ||
672 | * @entity: pointer to &media_entity | ||
673 | * | ||
674 | * Note: this is called automatically when an entity is unregistered via | ||
675 | * media_device_register_entity(). | ||
676 | */ | ||
143 | void media_entity_remove_links(struct media_entity *entity); | 677 | void media_entity_remove_links(struct media_entity *entity); |
144 | 678 | ||
679 | /** | ||
680 | * __media_entity_setup_link - Configure a media link without locking | ||
681 | * @link: The link being configured | ||
682 | * @flags: Link configuration flags | ||
683 | * | ||
684 | * The bulk of link setup is handled by the two entities connected through the | ||
685 | * link. This function notifies both entities of the link configuration change. | ||
686 | * | ||
687 | * If the link is immutable or if the current and new configuration are | ||
688 | * identical, return immediately. | ||
689 | * | ||
690 | * The user is expected to hold link->source->parent->mutex. If not, | ||
691 | * media_entity_setup_link() should be used instead. | ||
692 | */ | ||
145 | int __media_entity_setup_link(struct media_link *link, u32 flags); | 693 | int __media_entity_setup_link(struct media_link *link, u32 flags); |
694 | |||
695 | /** | ||
696 | * media_entity_setup_link() - changes the link flags properties in runtime | ||
697 | * | ||
698 | * @link: pointer to &media_link | ||
699 | * @flags: the requested new link flags | ||
700 | * | ||
701 | * The only configurable property is the %MEDIA_LNK_FL_ENABLED link flag | ||
702 | * flag to enable/disable a link. Links marked with the | ||
703 | * %MEDIA_LNK_FL_IMMUTABLE link flag can not be enabled or disabled. | ||
704 | * | ||
705 | * When a link is enabled or disabled, the media framework calls the | ||
706 | * link_setup operation for the two entities at the source and sink of the | ||
707 | * link, in that order. If the second link_setup call fails, another | ||
708 | * link_setup call is made on the first entity to restore the original link | ||
709 | * flags. | ||
710 | * | ||
711 | * Media device drivers can be notified of link setup operations by setting the | ||
712 | * media_device::link_notify pointer to a callback function. If provided, the | ||
713 | * notification callback will be called before enabling and after disabling | ||
714 | * links. | ||
715 | * | ||
716 | * Entity drivers must implement the link_setup operation if any of their links | ||
717 | * is non-immutable. The operation must either configure the hardware or store | ||
718 | * the configuration information to be applied later. | ||
719 | * | ||
720 | * Link configuration must not have any side effect on other links. If an | ||
721 | * enabled link at a sink pad prevents another link at the same pad from | ||
722 | * being enabled, the link_setup operation must return -EBUSY and can't | ||
723 | * implicitly disable the first enabled link. | ||
724 | * | ||
725 | * NOTE: the valid values of the flags for the link is the same as described | ||
726 | * on media_create_pad_link(), for pad to pad links or the same as described | ||
727 | * on media_create_intf_link(), for interface to entity links. | ||
728 | */ | ||
146 | int media_entity_setup_link(struct media_link *link, u32 flags); | 729 | int media_entity_setup_link(struct media_link *link, u32 flags); |
730 | |||
731 | /** | ||
732 | * media_entity_find_link - Find a link between two pads | ||
733 | * @source: Source pad | ||
734 | * @sink: Sink pad | ||
735 | * | ||
736 | * Return a pointer to the link between the two entities. If no such link | ||
737 | * exists, return NULL. | ||
738 | */ | ||
147 | struct media_link *media_entity_find_link(struct media_pad *source, | 739 | struct media_link *media_entity_find_link(struct media_pad *source, |
148 | struct media_pad *sink); | 740 | struct media_pad *sink); |
741 | |||
742 | /** | ||
743 | * media_entity_remote_pad - Find the pad at the remote end of a link | ||
744 | * @pad: Pad at the local end of the link | ||
745 | * | ||
746 | * Search for a remote pad connected to the given pad by iterating over all | ||
747 | * links originating or terminating at that pad until an enabled link is found. | ||
748 | * | ||
749 | * Return a pointer to the pad at the remote end of the first found enabled | ||
750 | * link, or NULL if no enabled link has been found. | ||
751 | */ | ||
149 | struct media_pad *media_entity_remote_pad(struct media_pad *pad); | 752 | struct media_pad *media_entity_remote_pad(struct media_pad *pad); |
150 | 753 | ||
754 | /** | ||
755 | * media_entity_get - Get a reference to the parent module | ||
756 | * | ||
757 | * @entity: The entity | ||
758 | * | ||
759 | * Get a reference to the parent media device module. | ||
760 | * | ||
761 | * The function will return immediately if @entity is NULL. | ||
762 | * | ||
763 | * Return a pointer to the entity on success or NULL on failure. | ||
764 | */ | ||
151 | struct media_entity *media_entity_get(struct media_entity *entity); | 765 | struct media_entity *media_entity_get(struct media_entity *entity); |
766 | |||
767 | __must_check int media_entity_graph_walk_init( | ||
768 | struct media_entity_graph *graph, struct media_device *mdev); | ||
769 | |||
770 | /** | ||
771 | * media_entity_graph_walk_cleanup - Release resources used by graph walk. | ||
772 | * | ||
773 | * @graph: Media graph structure that will be used to walk the graph | ||
774 | */ | ||
775 | void media_entity_graph_walk_cleanup(struct media_entity_graph *graph); | ||
776 | |||
777 | /** | ||
778 | * media_entity_put - Release the reference to the parent module | ||
779 | * | ||
780 | * @entity: The entity | ||
781 | * | ||
782 | * Release the reference count acquired by media_entity_get(). | ||
783 | * | ||
784 | * The function will return immediately if @entity is NULL. | ||
785 | */ | ||
152 | void media_entity_put(struct media_entity *entity); | 786 | void media_entity_put(struct media_entity *entity); |
153 | 787 | ||
788 | /** | ||
789 | * media_entity_graph_walk_start - Start walking the media graph at a given entity | ||
790 | * @graph: Media graph structure that will be used to walk the graph | ||
791 | * @entity: Starting entity | ||
792 | * | ||
793 | * Before using this function, media_entity_graph_walk_init() must be | ||
794 | * used to allocate resources used for walking the graph. This | ||
795 | * function initializes the graph traversal structure to walk the | ||
796 | * entities graph starting at the given entity. The traversal | ||
797 | * structure must not be modified by the caller during graph | ||
798 | * traversal. After the graph walk, the resources must be released | ||
799 | * using media_entity_graph_walk_cleanup(). | ||
800 | */ | ||
154 | void media_entity_graph_walk_start(struct media_entity_graph *graph, | 801 | void media_entity_graph_walk_start(struct media_entity_graph *graph, |
155 | struct media_entity *entity); | 802 | struct media_entity *entity); |
803 | |||
804 | /** | ||
805 | * media_entity_graph_walk_next - Get the next entity in the graph | ||
806 | * @graph: Media graph structure | ||
807 | * | ||
808 | * Perform a depth-first traversal of the given media entities graph. | ||
809 | * | ||
810 | * The graph structure must have been previously initialized with a call to | ||
811 | * media_entity_graph_walk_start(). | ||
812 | * | ||
813 | * Return the next entity in the graph or NULL if the whole graph have been | ||
814 | * traversed. | ||
815 | */ | ||
156 | struct media_entity * | 816 | struct media_entity * |
157 | media_entity_graph_walk_next(struct media_entity_graph *graph); | 817 | media_entity_graph_walk_next(struct media_entity_graph *graph); |
818 | |||
819 | /** | ||
820 | * media_entity_pipeline_start - Mark a pipeline as streaming | ||
821 | * @entity: Starting entity | ||
822 | * @pipe: Media pipeline to be assigned to all entities in the pipeline. | ||
823 | * | ||
824 | * Mark all entities connected to a given entity through enabled links, either | ||
825 | * directly or indirectly, as streaming. The given pipeline object is assigned to | ||
826 | * every entity in the pipeline and stored in the media_entity pipe field. | ||
827 | * | ||
828 | * Calls to this function can be nested, in which case the same number of | ||
829 | * media_entity_pipeline_stop() calls will be required to stop streaming. The | ||
830 | * pipeline pointer must be identical for all nested calls to | ||
831 | * media_entity_pipeline_start(). | ||
832 | */ | ||
158 | __must_check int media_entity_pipeline_start(struct media_entity *entity, | 833 | __must_check int media_entity_pipeline_start(struct media_entity *entity, |
159 | struct media_pipeline *pipe); | 834 | struct media_pipeline *pipe); |
835 | |||
836 | /** | ||
837 | * media_entity_pipeline_stop - Mark a pipeline as not streaming | ||
838 | * @entity: Starting entity | ||
839 | * | ||
840 | * Mark all entities connected to a given entity through enabled links, either | ||
841 | * directly or indirectly, as not streaming. The media_entity pipe field is | ||
842 | * reset to NULL. | ||
843 | * | ||
844 | * If multiple calls to media_entity_pipeline_start() have been made, the same | ||
845 | * number of calls to this function are required to mark the pipeline as not | ||
846 | * streaming. | ||
847 | */ | ||
160 | void media_entity_pipeline_stop(struct media_entity *entity); | 848 | void media_entity_pipeline_stop(struct media_entity *entity); |
161 | 849 | ||
850 | /** | ||
851 | * media_devnode_create() - creates and initializes a device node interface | ||
852 | * | ||
853 | * @mdev: pointer to struct &media_device | ||
854 | * @type: type of the interface, as given by MEDIA_INTF_T_* macros | ||
855 | * as defined in the uapi/media/media.h header. | ||
856 | * @flags: Interface flags as defined in uapi/media/media.h. | ||
857 | * @major: Device node major number. | ||
858 | * @minor: Device node minor number. | ||
859 | * | ||
860 | * Return: if succeeded, returns a pointer to the newly allocated | ||
861 | * &media_intf_devnode pointer. | ||
862 | */ | ||
863 | struct media_intf_devnode * | ||
864 | __must_check media_devnode_create(struct media_device *mdev, | ||
865 | u32 type, u32 flags, | ||
866 | u32 major, u32 minor); | ||
867 | /** | ||
868 | * media_devnode_remove() - removes a device node interface | ||
869 | * | ||
870 | * @devnode: pointer to &media_intf_devnode to be freed. | ||
871 | * | ||
872 | * When a device node interface is removed, all links to it are automatically | ||
873 | * removed. | ||
874 | */ | ||
875 | void media_devnode_remove(struct media_intf_devnode *devnode); | ||
876 | struct media_link * | ||
877 | |||
878 | /** | ||
879 | * media_create_intf_link() - creates a link between an entity and an interface | ||
880 | * | ||
881 | * @entity: pointer to %media_entity | ||
882 | * @intf: pointer to %media_interface | ||
883 | * @flags: Link flags, as defined in include/uapi/linux/media.h. | ||
884 | * | ||
885 | * | ||
886 | * Valid values for flags: | ||
887 | * The %MEDIA_LNK_FL_ENABLED flag indicates that the interface is connected to | ||
888 | * the entity hardware. That's the default value for interfaces. An | ||
889 | * interface may be disabled if the hardware is busy due to the usage | ||
890 | * of some other interface that it is currently controlling the hardware. | ||
891 | * A typical example is an hybrid TV device that handle only one type of | ||
892 | * stream on a given time. So, when the digital TV is streaming, | ||
893 | * the V4L2 interfaces won't be enabled, as such device is not able to | ||
894 | * also stream analog TV or radio. | ||
895 | * | ||
896 | * Note: | ||
897 | * | ||
898 | * Before calling this function, media_devnode_create() should be called for | ||
899 | * the interface and media_device_register_entity() should be called for the | ||
900 | * interface that will be part of the link. | ||
901 | */ | ||
902 | __must_check media_create_intf_link(struct media_entity *entity, | ||
903 | struct media_interface *intf, | ||
904 | u32 flags); | ||
905 | /** | ||
906 | * __media_remove_intf_link() - remove a single interface link | ||
907 | * | ||
908 | * @link: pointer to &media_link. | ||
909 | * | ||
910 | * Note: this is an unlocked version of media_remove_intf_link() | ||
911 | */ | ||
912 | void __media_remove_intf_link(struct media_link *link); | ||
913 | |||
914 | /** | ||
915 | * media_remove_intf_link() - remove a single interface link | ||
916 | * | ||
917 | * @link: pointer to &media_link. | ||
918 | * | ||
919 | * Note: prefer to use this one, instead of __media_remove_intf_link() | ||
920 | */ | ||
921 | void media_remove_intf_link(struct media_link *link); | ||
922 | |||
923 | /** | ||
924 | * __media_remove_intf_links() - remove all links associated with an interface | ||
925 | * | ||
926 | * @intf: pointer to &media_interface | ||
927 | * | ||
928 | * Note: this is an unlocked version of media_remove_intf_links(). | ||
929 | */ | ||
930 | void __media_remove_intf_links(struct media_interface *intf); | ||
931 | |||
932 | /** | ||
933 | * media_remove_intf_links() - remove all links associated with an interface | ||
934 | * | ||
935 | * @intf: pointer to &media_interface | ||
936 | * | ||
937 | * Notes: | ||
938 | * | ||
939 | * this is called automatically when an entity is unregistered via | ||
940 | * media_device_register_entity() and by media_devnode_remove(). | ||
941 | * | ||
942 | * Prefer to use this one, instead of __media_remove_intf_links(). | ||
943 | */ | ||
944 | void media_remove_intf_links(struct media_interface *intf); | ||
945 | |||
162 | #define media_entity_call(entity, operation, args...) \ | 946 | #define media_entity_call(entity, operation, args...) \ |
163 | (((entity)->ops && (entity)->ops->operation) ? \ | 947 | (((entity)->ops && (entity)->ops->operation) ? \ |
164 | (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD) | 948 | (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD) |
diff --git a/include/media/tuner.h b/include/media/tuner.h index 486b6a54363b..e5321fda5489 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h | |||
@@ -21,6 +21,14 @@ | |||
21 | 21 | ||
22 | #include <linux/videodev2.h> | 22 | #include <linux/videodev2.h> |
23 | 23 | ||
24 | /* Tuner PADs */ | ||
25 | /* FIXME: is this the right place for it? */ | ||
26 | enum tuner_pad_index { | ||
27 | TUNER_PAD_RF_INPUT, | ||
28 | TUNER_PAD_IF_OUTPUT, | ||
29 | TUNER_NUM_PADS | ||
30 | }; | ||
31 | |||
24 | #define ADDR_UNSET (255) | 32 | #define ADDR_UNSET (255) |
25 | 33 | ||
26 | #define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */ | 34 | #define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */ |
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index acbcd2f5fe7f..eeabf20e87a6 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h | |||
@@ -86,6 +86,7 @@ struct video_device | |||
86 | { | 86 | { |
87 | #if defined(CONFIG_MEDIA_CONTROLLER) | 87 | #if defined(CONFIG_MEDIA_CONTROLLER) |
88 | struct media_entity entity; | 88 | struct media_entity entity; |
89 | struct media_intf_devnode *intf_devnode; | ||
89 | #endif | 90 | #endif |
90 | /* device ops */ | 91 | /* device ops */ |
91 | const struct v4l2_file_operations *fops; | 92 | const struct v4l2_file_operations *fops; |
diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 4e816be3de39..1e3c8cb43bd7 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h | |||
@@ -23,6 +23,9 @@ | |||
23 | #ifndef __LINUX_MEDIA_H | 23 | #ifndef __LINUX_MEDIA_H |
24 | #define __LINUX_MEDIA_H | 24 | #define __LINUX_MEDIA_H |
25 | 25 | ||
26 | #ifndef __KERNEL__ | ||
27 | #include <stdint.h> | ||
28 | #endif | ||
26 | #include <linux/ioctl.h> | 29 | #include <linux/ioctl.h> |
27 | #include <linux/types.h> | 30 | #include <linux/types.h> |
28 | #include <linux/version.h> | 31 | #include <linux/version.h> |
@@ -42,33 +45,107 @@ struct media_device_info { | |||
42 | 45 | ||
43 | #define MEDIA_ENT_ID_FLAG_NEXT (1 << 31) | 46 | #define MEDIA_ENT_ID_FLAG_NEXT (1 << 31) |
44 | 47 | ||
48 | /* | ||
49 | * Initial value to be used when a new entity is created | ||
50 | * Drivers should change it to something useful | ||
51 | */ | ||
52 | #define MEDIA_ENT_F_UNKNOWN 0x00000000 | ||
53 | |||
54 | /* | ||
55 | * Base number ranges for entity functions | ||
56 | * | ||
57 | * NOTE: those ranges and entity function number are phased just to | ||
58 | * make it easier to maintain this file. Userspace should not rely on | ||
59 | * the ranges to identify a group of function types, as newer | ||
60 | * functions can be added with any name within the full u32 range. | ||
61 | */ | ||
62 | #define MEDIA_ENT_F_BASE 0x00000000 | ||
63 | #define MEDIA_ENT_F_OLD_BASE 0x00010000 | ||
64 | #define MEDIA_ENT_F_OLD_SUBDEV_BASE 0x00020000 | ||
65 | |||
66 | /* | ||
67 | * DVB entities | ||
68 | */ | ||
69 | #define MEDIA_ENT_F_DTV_DEMOD (MEDIA_ENT_F_BASE + 1) | ||
70 | #define MEDIA_ENT_F_TS_DEMUX (MEDIA_ENT_F_BASE + 2) | ||
71 | #define MEDIA_ENT_F_DTV_CA (MEDIA_ENT_F_BASE + 3) | ||
72 | #define MEDIA_ENT_F_DTV_NET_DECAP (MEDIA_ENT_F_BASE + 4) | ||
73 | |||
74 | /* | ||
75 | * Connectors | ||
76 | */ | ||
77 | /* It is a responsibility of the entity drivers to add connectors and links */ | ||
78 | #define MEDIA_ENT_F_CONN_RF (MEDIA_ENT_F_BASE + 21) | ||
79 | #define MEDIA_ENT_F_CONN_SVIDEO (MEDIA_ENT_F_BASE + 22) | ||
80 | #define MEDIA_ENT_F_CONN_COMPOSITE (MEDIA_ENT_F_BASE + 23) | ||
81 | /* For internal test signal generators and other debug connectors */ | ||
82 | #define MEDIA_ENT_F_CONN_TEST (MEDIA_ENT_F_BASE + 24) | ||
83 | |||
84 | /* | ||
85 | * I/O entities | ||
86 | */ | ||
87 | #define MEDIA_ENT_F_IO_DTV (MEDIA_ENT_F_BASE + 31) | ||
88 | #define MEDIA_ENT_F_IO_VBI (MEDIA_ENT_F_BASE + 32) | ||
89 | #define MEDIA_ENT_F_IO_SWRADIO (MEDIA_ENT_F_BASE + 33) | ||
90 | |||
91 | /* | ||
92 | * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and | ||
93 | * MEDIA_ENT_F_OLD_SUBDEV_BASE are kept to keep backward compatibility | ||
94 | * with the legacy v1 API.The number range is out of range by purpose: | ||
95 | * several previously reserved numbers got excluded from this range. | ||
96 | * | ||
97 | * Subdevs are initialized with MEDIA_ENT_T_V4L2_SUBDEV_UNKNOWN, | ||
98 | * in order to preserve backward compatibility. | ||
99 | * Drivers must change to the proper subdev type before | ||
100 | * registering the entity. | ||
101 | */ | ||
102 | |||
103 | #define MEDIA_ENT_F_IO_V4L (MEDIA_ENT_F_OLD_BASE + 1) | ||
104 | |||
105 | #define MEDIA_ENT_F_CAM_SENSOR (MEDIA_ENT_F_OLD_SUBDEV_BASE + 1) | ||
106 | #define MEDIA_ENT_F_FLASH (MEDIA_ENT_F_OLD_SUBDEV_BASE + 2) | ||
107 | #define MEDIA_ENT_F_LENS (MEDIA_ENT_F_OLD_SUBDEV_BASE + 3) | ||
108 | #define MEDIA_ENT_F_ATV_DECODER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 4) | ||
109 | /* | ||
110 | * It is a responsibility of the entity drivers to add connectors and links | ||
111 | * for the tuner entities. | ||
112 | */ | ||
113 | #define MEDIA_ENT_F_TUNER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 5) | ||
114 | |||
115 | #define MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN MEDIA_ENT_F_OLD_SUBDEV_BASE | ||
116 | |||
117 | #ifndef __KERNEL__ | ||
118 | |||
119 | /* | ||
120 | * Legacy symbols used to avoid userspace compilation breakages | ||
121 | * | ||
122 | * Those symbols map the entity function into types and should be | ||
123 | * used only on legacy programs for legacy hardware. Don't rely | ||
124 | * on those for MEDIA_IOC_G_TOPOLOGY. | ||
125 | */ | ||
45 | #define MEDIA_ENT_TYPE_SHIFT 16 | 126 | #define MEDIA_ENT_TYPE_SHIFT 16 |
46 | #define MEDIA_ENT_TYPE_MASK 0x00ff0000 | 127 | #define MEDIA_ENT_TYPE_MASK 0x00ff0000 |
47 | #define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff | 128 | #define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff |
48 | 129 | ||
49 | #define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENT_TYPE_SHIFT) | 130 | #define MEDIA_ENT_T_DEVNODE MEDIA_ENT_F_OLD_BASE |
50 | #define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENT_T_DEVNODE + 1) | 131 | #define MEDIA_ENT_T_DEVNODE_V4L MEDIA_ENT_F_IO_V4L |
51 | #define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENT_T_DEVNODE + 2) | 132 | #define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENT_T_DEVNODE + 2) |
52 | #define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENT_T_DEVNODE + 3) | 133 | #define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENT_T_DEVNODE + 3) |
53 | #define MEDIA_ENT_T_DEVNODE_DVB_FE (MEDIA_ENT_T_DEVNODE + 4) | 134 | #define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENT_T_DEVNODE + 4) |
54 | #define MEDIA_ENT_T_DEVNODE_DVB_DEMUX (MEDIA_ENT_T_DEVNODE + 5) | ||
55 | #define MEDIA_ENT_T_DEVNODE_DVB_DVR (MEDIA_ENT_T_DEVNODE + 6) | ||
56 | #define MEDIA_ENT_T_DEVNODE_DVB_CA (MEDIA_ENT_T_DEVNODE + 7) | ||
57 | #define MEDIA_ENT_T_DEVNODE_DVB_NET (MEDIA_ENT_T_DEVNODE + 8) | ||
58 | |||
59 | /* Legacy symbol. Use it to avoid userspace compilation breakages */ | ||
60 | #define MEDIA_ENT_T_DEVNODE_DVB MEDIA_ENT_T_DEVNODE_DVB_FE | ||
61 | |||
62 | #define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENT_TYPE_SHIFT) | ||
63 | #define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENT_T_V4L2_SUBDEV + 1) | ||
64 | #define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENT_T_V4L2_SUBDEV + 2) | ||
65 | #define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENT_T_V4L2_SUBDEV + 3) | ||
66 | /* A converter of analogue video to its digital representation. */ | ||
67 | #define MEDIA_ENT_T_V4L2_SUBDEV_DECODER (MEDIA_ENT_T_V4L2_SUBDEV + 4) | ||
68 | 135 | ||
69 | #define MEDIA_ENT_T_V4L2_SUBDEV_TUNER (MEDIA_ENT_T_V4L2_SUBDEV + 5) | 136 | #define MEDIA_ENT_T_UNKNOWN MEDIA_ENT_F_UNKNOWN |
137 | #define MEDIA_ENT_T_V4L2_VIDEO MEDIA_ENT_F_IO_V4L | ||
138 | #define MEDIA_ENT_T_V4L2_SUBDEV MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN | ||
139 | #define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR MEDIA_ENT_F_CAM_SENSOR | ||
140 | #define MEDIA_ENT_T_V4L2_SUBDEV_FLASH MEDIA_ENT_F_FLASH | ||
141 | #define MEDIA_ENT_T_V4L2_SUBDEV_LENS MEDIA_ENT_F_LENS | ||
142 | #define MEDIA_ENT_T_V4L2_SUBDEV_DECODER MEDIA_ENT_F_ATV_DECODER | ||
143 | #define MEDIA_ENT_T_V4L2_SUBDEV_TUNER MEDIA_ENT_F_TUNER | ||
144 | #endif | ||
70 | 145 | ||
146 | /* Entity flags */ | ||
71 | #define MEDIA_ENT_FL_DEFAULT (1 << 0) | 147 | #define MEDIA_ENT_FL_DEFAULT (1 << 0) |
148 | #define MEDIA_ENT_FL_CONNECTOR (1 << 1) | ||
72 | 149 | ||
73 | struct media_entity_desc { | 150 | struct media_entity_desc { |
74 | __u32 id; | 151 | __u32 id; |
@@ -151,6 +228,10 @@ struct media_pad_desc { | |||
151 | #define MEDIA_LNK_FL_IMMUTABLE (1 << 1) | 228 | #define MEDIA_LNK_FL_IMMUTABLE (1 << 1) |
152 | #define MEDIA_LNK_FL_DYNAMIC (1 << 2) | 229 | #define MEDIA_LNK_FL_DYNAMIC (1 << 2) |
153 | 230 | ||
231 | #define MEDIA_LNK_FL_LINK_TYPE (0xf << 28) | ||
232 | # define MEDIA_LNK_FL_DATA_LINK (0 << 28) | ||
233 | # define MEDIA_LNK_FL_INTERFACE_LINK (1 << 28) | ||
234 | |||
154 | struct media_link_desc { | 235 | struct media_link_desc { |
155 | struct media_pad_desc source; | 236 | struct media_pad_desc source; |
156 | struct media_pad_desc sink; | 237 | struct media_pad_desc sink; |
@@ -167,9 +248,120 @@ struct media_links_enum { | |||
167 | __u32 reserved[4]; | 248 | __u32 reserved[4]; |
168 | }; | 249 | }; |
169 | 250 | ||
251 | /* Interface type ranges */ | ||
252 | |||
253 | #define MEDIA_INTF_T_DVB_BASE 0x00000100 | ||
254 | #define MEDIA_INTF_T_V4L_BASE 0x00000200 | ||
255 | |||
256 | /* Interface types */ | ||
257 | |||
258 | #define MEDIA_INTF_T_DVB_FE (MEDIA_INTF_T_DVB_BASE) | ||
259 | #define MEDIA_INTF_T_DVB_DEMUX (MEDIA_INTF_T_DVB_BASE + 1) | ||
260 | #define MEDIA_INTF_T_DVB_DVR (MEDIA_INTF_T_DVB_BASE + 2) | ||
261 | #define MEDIA_INTF_T_DVB_CA (MEDIA_INTF_T_DVB_BASE + 3) | ||
262 | #define MEDIA_INTF_T_DVB_NET (MEDIA_INTF_T_DVB_BASE + 4) | ||
263 | |||
264 | #define MEDIA_INTF_T_V4L_VIDEO (MEDIA_INTF_T_V4L_BASE) | ||
265 | #define MEDIA_INTF_T_V4L_VBI (MEDIA_INTF_T_V4L_BASE + 1) | ||
266 | #define MEDIA_INTF_T_V4L_RADIO (MEDIA_INTF_T_V4L_BASE + 2) | ||
267 | #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3) | ||
268 | #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4) | ||
269 | |||
270 | /* | ||
271 | * MC next gen API definitions | ||
272 | * | ||
273 | * NOTE: The declarations below are close to the MC RFC for the Media | ||
274 | * Controller, the next generation. Yet, there are a few adjustments | ||
275 | * to do, as we want to be able to have a functional API before | ||
276 | * the MC properties change. Those will be properly marked below. | ||
277 | * Please also notice that I removed "num_pads", "num_links", | ||
278 | * from the proposal, as a proper userspace application will likely | ||
279 | * use lists for pads/links, just as we intend to do in Kernelspace. | ||
280 | * The API definition should be freed from fields that are bound to | ||
281 | * some specific data structure. | ||
282 | * | ||
283 | * FIXME: Currently, I opted to name the new types as "media_v2", as this | ||
284 | * won't cause any conflict with the Kernelspace namespace, nor with | ||
285 | * the previous kAPI media_*_desc namespace. This can be changed | ||
286 | * later, before the adding this API upstream. | ||
287 | */ | ||
288 | |||
289 | #if 0 /* Let's postpone it to Kernel 4.6 */ | ||
290 | struct media_v2_entity { | ||
291 | __u32 id; | ||
292 | char name[64]; /* FIXME: move to a property? (RFC says so) */ | ||
293 | __u32 function; /* Main function of the entity */ | ||
294 | __u16 reserved[12]; | ||
295 | }; | ||
296 | |||
297 | /* Should match the specific fields at media_intf_devnode */ | ||
298 | struct media_v2_intf_devnode { | ||
299 | __u32 major; | ||
300 | __u32 minor; | ||
301 | }; | ||
302 | |||
303 | struct media_v2_interface { | ||
304 | __u32 id; | ||
305 | __u32 intf_type; | ||
306 | __u32 flags; | ||
307 | __u32 reserved[9]; | ||
308 | |||
309 | union { | ||
310 | struct media_v2_intf_devnode devnode; | ||
311 | __u32 raw[16]; | ||
312 | }; | ||
313 | }; | ||
314 | |||
315 | struct media_v2_pad { | ||
316 | __u32 id; | ||
317 | __u32 entity_id; | ||
318 | __u32 flags; | ||
319 | __u16 reserved[9]; | ||
320 | }; | ||
321 | |||
322 | struct media_v2_link { | ||
323 | __u32 id; | ||
324 | __u32 source_id; | ||
325 | __u32 sink_id; | ||
326 | __u32 flags; | ||
327 | __u32 reserved[5]; | ||
328 | }; | ||
329 | |||
330 | struct media_v2_topology { | ||
331 | __u64 topology_version; | ||
332 | |||
333 | __u32 num_entities; | ||
334 | __u32 reserved1; | ||
335 | __u64 ptr_entities; | ||
336 | |||
337 | __u32 num_interfaces; | ||
338 | __u32 reserved2; | ||
339 | __u64 ptr_interfaces; | ||
340 | |||
341 | __u32 num_pads; | ||
342 | __u32 reserved3; | ||
343 | __u64 ptr_pads; | ||
344 | |||
345 | __u32 num_links; | ||
346 | __u32 reserved4; | ||
347 | __u64 ptr_links; | ||
348 | }; | ||
349 | |||
350 | static inline void __user *media_get_uptr(__u64 arg) | ||
351 | { | ||
352 | return (void __user *)(uintptr_t)arg; | ||
353 | } | ||
354 | #endif | ||
355 | |||
356 | /* ioctls */ | ||
357 | |||
170 | #define MEDIA_IOC_DEVICE_INFO _IOWR('|', 0x00, struct media_device_info) | 358 | #define MEDIA_IOC_DEVICE_INFO _IOWR('|', 0x00, struct media_device_info) |
171 | #define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc) | 359 | #define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc) |
172 | #define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum) | 360 | #define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum) |
173 | #define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc) | 361 | #define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc) |
174 | 362 | ||
363 | #if 0 /* Let's postpone it to Kernel 4.6 */ | ||
364 | #define MEDIA_IOC_G_TOPOLOGY _IOWR('|', 0x04, struct media_v2_topology) | ||
365 | #endif | ||
366 | |||
175 | #endif /* __LINUX_MEDIA_H */ | 367 | #endif /* __LINUX_MEDIA_H */ |