hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/media/v4l2-core/v4l2-mc.c
....@@ -28,7 +28,7 @@
2828 struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL;
2929 bool is_webcam = false;
3030 u32 flags;
31
- int ret;
31
+ int ret, pad_sink, pad_source;
3232
3333 if (!mdev)
3434 return 0;
....@@ -63,8 +63,10 @@
6363 }
6464
6565 /* It should have at least one I/O entity */
66
- if (!io_v4l && !io_vbi && !io_swradio)
66
+ if (!io_v4l && !io_vbi && !io_swradio) {
67
+ dev_warn(mdev->dev, "Didn't find any I/O entity\n");
6768 return -EINVAL;
69
+ }
6870
6971 /*
7072 * Here, webcams are modelled on a very simple way: the sensor is
....@@ -74,8 +76,10 @@
7476 * PC-consumer's hardware.
7577 */
7678 if (is_webcam) {
77
- if (!io_v4l)
79
+ if (!io_v4l) {
80
+ dev_warn(mdev->dev, "Didn't find a MEDIA_ENT_F_IO_V4L\n");
7881 return -EINVAL;
82
+ }
7983
8084 media_device_for_each_entity(entity, mdev) {
8185 if (entity->function != MEDIA_ENT_F_CAM_SENSOR)
....@@ -83,46 +87,91 @@
8387 ret = media_create_pad_link(entity, 0,
8488 io_v4l, 0,
8589 MEDIA_LNK_FL_ENABLED);
86
- if (ret)
90
+ if (ret) {
91
+ dev_warn(mdev->dev, "Failed to create a sensor link\n");
8792 return ret;
93
+ }
8894 }
8995 if (!decoder)
9096 return 0;
9197 }
9298
9399 /* The device isn't a webcam. So, it should have a decoder */
94
- if (!decoder)
100
+ if (!decoder) {
101
+ dev_warn(mdev->dev, "Decoder not found\n");
95102 return -EINVAL;
103
+ }
96104
97105 /* Link the tuner and IF video output pads */
98106 if (tuner) {
99107 if (if_vid) {
100
- ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
101
- if_vid,
102
- IF_VID_DEC_PAD_IF_INPUT,
108
+ pad_source = media_get_pad_index(tuner, false,
109
+ PAD_SIGNAL_ANALOG);
110
+ pad_sink = media_get_pad_index(if_vid, true,
111
+ PAD_SIGNAL_ANALOG);
112
+ if (pad_source < 0 || pad_sink < 0) {
113
+ dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n",
114
+ pad_source, pad_sink);
115
+ return -EINVAL;
116
+ }
117
+ ret = media_create_pad_link(tuner, pad_source,
118
+ if_vid, pad_sink,
103119 MEDIA_LNK_FL_ENABLED);
104
- if (ret)
120
+ if (ret) {
121
+ dev_warn(mdev->dev, "Couldn't create tuner->PLL link)\n");
105122 return ret;
106
- ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
107
- decoder, DEMOD_PAD_IF_INPUT,
108
- MEDIA_LNK_FL_ENABLED);
109
- if (ret)
123
+ }
124
+
125
+ pad_source = media_get_pad_index(if_vid, false,
126
+ PAD_SIGNAL_ANALOG);
127
+ pad_sink = media_get_pad_index(decoder, true,
128
+ PAD_SIGNAL_ANALOG);
129
+ if (pad_source < 0 || pad_sink < 0) {
130
+ dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n",
131
+ pad_source, pad_sink);
132
+ return -EINVAL;
133
+ }
134
+ ret = media_create_pad_link(if_vid, pad_source,
135
+ decoder, pad_sink,
136
+ MEDIA_LNK_FL_ENABLED);
137
+ if (ret) {
138
+ dev_warn(mdev->dev, "couldn't link PLL to decoder\n");
110139 return ret;
140
+ }
111141 } else {
112
- ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
113
- decoder, DEMOD_PAD_IF_INPUT,
114
- MEDIA_LNK_FL_ENABLED);
142
+ pad_source = media_get_pad_index(tuner, false,
143
+ PAD_SIGNAL_ANALOG);
144
+ pad_sink = media_get_pad_index(decoder, true,
145
+ PAD_SIGNAL_ANALOG);
146
+ if (pad_source < 0 || pad_sink < 0) {
147
+ dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n",
148
+ pad_source, pad_sink);
149
+ return -EINVAL;
150
+ }
151
+ ret = media_create_pad_link(tuner, pad_source,
152
+ decoder, pad_sink,
153
+ MEDIA_LNK_FL_ENABLED);
115154 if (ret)
116155 return ret;
117156 }
118157
119158 if (if_aud) {
120
- ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
121
- if_aud,
122
- IF_AUD_DEC_PAD_IF_INPUT,
159
+ pad_source = media_get_pad_index(tuner, false,
160
+ PAD_SIGNAL_AUDIO);
161
+ pad_sink = media_get_pad_index(if_aud, true,
162
+ PAD_SIGNAL_AUDIO);
163
+ if (pad_source < 0 || pad_sink < 0) {
164
+ dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n",
165
+ pad_source, pad_sink);
166
+ return -EINVAL;
167
+ }
168
+ ret = media_create_pad_link(tuner, pad_source,
169
+ if_aud, pad_sink,
123170 MEDIA_LNK_FL_ENABLED);
124
- if (ret)
171
+ if (ret) {
172
+ dev_warn(mdev->dev, "couldn't link tuner->audio PLL\n");
125173 return ret;
174
+ }
126175 } else {
127176 if_aud = tuner;
128177 }
....@@ -131,27 +180,48 @@
131180
132181 /* Create demod to V4L, VBI and SDR radio links */
133182 if (io_v4l) {
134
- ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
135
- io_v4l, 0,
136
- MEDIA_LNK_FL_ENABLED);
137
- if (ret)
183
+ pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
184
+ if (pad_source < 0) {
185
+ dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n");
186
+ return -EINVAL;
187
+ }
188
+ ret = media_create_pad_link(decoder, pad_source,
189
+ io_v4l, 0,
190
+ MEDIA_LNK_FL_ENABLED);
191
+ if (ret) {
192
+ dev_warn(mdev->dev, "couldn't link decoder output to V4L I/O\n");
138193 return ret;
194
+ }
139195 }
140196
141197 if (io_swradio) {
142
- ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
143
- io_swradio, 0,
144
- MEDIA_LNK_FL_ENABLED);
145
- if (ret)
198
+ pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
199
+ if (pad_source < 0) {
200
+ dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n");
201
+ return -EINVAL;
202
+ }
203
+ ret = media_create_pad_link(decoder, pad_source,
204
+ io_swradio, 0,
205
+ MEDIA_LNK_FL_ENABLED);
206
+ if (ret) {
207
+ dev_warn(mdev->dev, "couldn't link decoder output to SDR\n");
146208 return ret;
209
+ }
147210 }
148211
149212 if (io_vbi) {
150
- ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
213
+ pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
214
+ if (pad_source < 0) {
215
+ dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n");
216
+ return -EINVAL;
217
+ }
218
+ ret = media_create_pad_link(decoder, pad_source,
151219 io_vbi, 0,
152220 MEDIA_LNK_FL_ENABLED);
153
- if (ret)
221
+ if (ret) {
222
+ dev_warn(mdev->dev, "couldn't link decoder output to VBI\n");
154223 return ret;
224
+ }
155225 }
156226
157227 /* Create links for the media connectors */
....@@ -161,15 +231,26 @@
161231 case MEDIA_ENT_F_CONN_RF:
162232 if (!tuner)
163233 continue;
164
-
234
+ pad_sink = media_get_pad_index(tuner, true,
235
+ PAD_SIGNAL_ANALOG);
236
+ if (pad_sink < 0) {
237
+ dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
238
+ return -EINVAL;
239
+ }
165240 ret = media_create_pad_link(entity, 0, tuner,
166
- TUNER_PAD_RF_INPUT,
241
+ pad_sink,
167242 flags);
168243 break;
169244 case MEDIA_ENT_F_CONN_SVIDEO:
170245 case MEDIA_ENT_F_CONN_COMPOSITE:
246
+ pad_sink = media_get_pad_index(decoder, true,
247
+ PAD_SIGNAL_ANALOG);
248
+ if (pad_sink < 0) {
249
+ dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
250
+ return -EINVAL;
251
+ }
171252 ret = media_create_pad_link(entity, 0, decoder,
172
- DEMOD_PAD_IF_INPUT,
253
+ pad_sink,
173254 flags);
174255 break;
175256 default:
....@@ -228,6 +309,101 @@
228309 }
229310 EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
230311
312
+int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
313
+ struct media_pad *sink)
314
+{
315
+ struct fwnode_handle *endpoint;
316
+ struct v4l2_subdev *sink_sd;
317
+
318
+ if (!(sink->flags & MEDIA_PAD_FL_SINK) ||
319
+ !is_media_entity_v4l2_subdev(sink->entity))
320
+ return -EINVAL;
321
+
322
+ sink_sd = media_entity_to_v4l2_subdev(sink->entity);
323
+
324
+ fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) {
325
+ struct fwnode_handle *remote_ep;
326
+ int src_idx, sink_idx, ret;
327
+ struct media_pad *src;
328
+
329
+ src_idx = media_entity_get_fwnode_pad(&src_sd->entity,
330
+ endpoint,
331
+ MEDIA_PAD_FL_SOURCE);
332
+ if (src_idx < 0)
333
+ continue;
334
+
335
+ remote_ep = fwnode_graph_get_remote_endpoint(endpoint);
336
+ if (!remote_ep)
337
+ continue;
338
+
339
+ /*
340
+ * ask the sink to verify it owns the remote endpoint,
341
+ * and translate to a sink pad.
342
+ */
343
+ sink_idx = media_entity_get_fwnode_pad(&sink_sd->entity,
344
+ remote_ep,
345
+ MEDIA_PAD_FL_SINK);
346
+ fwnode_handle_put(remote_ep);
347
+
348
+ if (sink_idx < 0 || sink_idx != sink->index)
349
+ continue;
350
+
351
+ /*
352
+ * the source endpoint corresponds to one of its source pads,
353
+ * the source endpoint connects to an endpoint at the sink
354
+ * entity, and the sink endpoint corresponds to the sink
355
+ * pad requested, so we have found an endpoint connection
356
+ * that works, create the media link for it.
357
+ */
358
+
359
+ src = &src_sd->entity.pads[src_idx];
360
+
361
+ /* skip if link already exists */
362
+ if (media_entity_find_link(src, sink))
363
+ continue;
364
+
365
+ dev_dbg(sink_sd->dev, "creating link %s:%d -> %s:%d\n",
366
+ src_sd->entity.name, src_idx,
367
+ sink_sd->entity.name, sink_idx);
368
+
369
+ ret = media_create_pad_link(&src_sd->entity, src_idx,
370
+ &sink_sd->entity, sink_idx, 0);
371
+ if (ret) {
372
+ dev_err(sink_sd->dev,
373
+ "link %s:%d -> %s:%d failed with %d\n",
374
+ src_sd->entity.name, src_idx,
375
+ sink_sd->entity.name, sink_idx, ret);
376
+
377
+ fwnode_handle_put(endpoint);
378
+ return ret;
379
+ }
380
+ }
381
+
382
+ return 0;
383
+}
384
+EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links_to_pad);
385
+
386
+int v4l2_create_fwnode_links(struct v4l2_subdev *src_sd,
387
+ struct v4l2_subdev *sink_sd)
388
+{
389
+ unsigned int i;
390
+
391
+ for (i = 0; i < sink_sd->entity.num_pads; i++) {
392
+ struct media_pad *pad = &sink_sd->entity.pads[i];
393
+ int ret;
394
+
395
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
396
+ continue;
397
+
398
+ ret = v4l2_create_fwnode_links_to_pad(src_sd, pad);
399
+ if (ret)
400
+ return ret;
401
+ }
402
+
403
+ return 0;
404
+}
405
+EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links);
406
+
231407 /* -----------------------------------------------------------------------------
232408 * Pipeline power management
233409 *
....@@ -240,7 +416,7 @@
240416 * use_count field stores the total number of users of all video device nodes
241417 * in the pipeline.
242418 *
243
- * The v4l2_pipeline_pm_use() function must be called in the open() and
419
+ * The v4l2_pipeline_pm_{get, put}() functions must be called in the open() and
244420 * close() handlers of video device nodes. It increments or decrements the use
245421 * count of all subdev entities in the pipeline.
246422 *
....@@ -342,7 +518,7 @@
342518 return ret;
343519 }
344520
345
-int v4l2_pipeline_pm_use(struct media_entity *entity, int use)
521
+static int v4l2_pipeline_pm_use(struct media_entity *entity, unsigned int use)
346522 {
347523 struct media_device *mdev = entity->graph_obj.mdev;
348524 int change = use ? 1 : -1;
....@@ -363,7 +539,19 @@
363539
364540 return ret;
365541 }
366
-EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_use);
542
+
543
+int v4l2_pipeline_pm_get(struct media_entity *entity)
544
+{
545
+ return v4l2_pipeline_pm_use(entity, 1);
546
+}
547
+EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_get);
548
+
549
+void v4l2_pipeline_pm_put(struct media_entity *entity)
550
+{
551
+ /* Powering off entities shouldn't fail. */
552
+ WARN_ON(v4l2_pipeline_pm_use(entity, 0));
553
+}
554
+EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_put);
367555
368556 int v4l2_pipeline_link_notify(struct media_link *link, u32 flags,
369557 unsigned int notification)