0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/module.h>
0013 #include <linux/pci.h>
0014 #include <linux/usb.h>
0015 #include <media/media-device.h>
0016 #include <media/media-entity.h>
0017 #include <media/v4l2-fh.h>
0018 #include <media/v4l2-mc.h>
0019 #include <media/v4l2-subdev.h>
0020 #include <media/videobuf2-core.h>
0021
0022 int v4l2_mc_create_media_graph(struct media_device *mdev)
0023
0024 {
0025 struct media_entity *entity;
0026 struct media_entity *if_vid = NULL, *if_aud = NULL;
0027 struct media_entity *tuner = NULL, *decoder = NULL;
0028 struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL;
0029 bool is_webcam = false;
0030 u32 flags;
0031 int ret, pad_sink, pad_source;
0032
0033 if (!mdev)
0034 return 0;
0035
0036 media_device_for_each_entity(entity, mdev) {
0037 switch (entity->function) {
0038 case MEDIA_ENT_F_IF_VID_DECODER:
0039 if_vid = entity;
0040 break;
0041 case MEDIA_ENT_F_IF_AUD_DECODER:
0042 if_aud = entity;
0043 break;
0044 case MEDIA_ENT_F_TUNER:
0045 tuner = entity;
0046 break;
0047 case MEDIA_ENT_F_ATV_DECODER:
0048 decoder = entity;
0049 break;
0050 case MEDIA_ENT_F_IO_V4L:
0051 io_v4l = entity;
0052 break;
0053 case MEDIA_ENT_F_IO_VBI:
0054 io_vbi = entity;
0055 break;
0056 case MEDIA_ENT_F_IO_SWRADIO:
0057 io_swradio = entity;
0058 break;
0059 case MEDIA_ENT_F_CAM_SENSOR:
0060 is_webcam = true;
0061 break;
0062 }
0063 }
0064
0065
0066 if (!io_v4l && !io_vbi && !io_swradio) {
0067 dev_warn(mdev->dev, "Didn't find any I/O entity\n");
0068 return -EINVAL;
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078 if (is_webcam) {
0079 if (!io_v4l) {
0080 dev_warn(mdev->dev, "Didn't find a MEDIA_ENT_F_IO_V4L\n");
0081 return -EINVAL;
0082 }
0083
0084 media_device_for_each_entity(entity, mdev) {
0085 if (entity->function != MEDIA_ENT_F_CAM_SENSOR)
0086 continue;
0087 ret = media_create_pad_link(entity, 0,
0088 io_v4l, 0,
0089 MEDIA_LNK_FL_ENABLED);
0090 if (ret) {
0091 dev_warn(mdev->dev, "Failed to create a sensor link\n");
0092 return ret;
0093 }
0094 }
0095 if (!decoder)
0096 return 0;
0097 }
0098
0099
0100 if (!decoder) {
0101 dev_warn(mdev->dev, "Decoder not found\n");
0102 return -EINVAL;
0103 }
0104
0105
0106 if (tuner) {
0107 if (if_vid) {
0108 pad_source = media_get_pad_index(tuner, false,
0109 PAD_SIGNAL_ANALOG);
0110 pad_sink = media_get_pad_index(if_vid, true,
0111 PAD_SIGNAL_ANALOG);
0112 if (pad_source < 0 || pad_sink < 0) {
0113 dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n",
0114 pad_source, pad_sink);
0115 return -EINVAL;
0116 }
0117 ret = media_create_pad_link(tuner, pad_source,
0118 if_vid, pad_sink,
0119 MEDIA_LNK_FL_ENABLED);
0120 if (ret) {
0121 dev_warn(mdev->dev, "Couldn't create tuner->PLL link)\n");
0122 return ret;
0123 }
0124
0125 pad_source = media_get_pad_index(if_vid, false,
0126 PAD_SIGNAL_ANALOG);
0127 pad_sink = media_get_pad_index(decoder, true,
0128 PAD_SIGNAL_ANALOG);
0129 if (pad_source < 0 || pad_sink < 0) {
0130 dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n",
0131 pad_source, pad_sink);
0132 return -EINVAL;
0133 }
0134 ret = media_create_pad_link(if_vid, pad_source,
0135 decoder, pad_sink,
0136 MEDIA_LNK_FL_ENABLED);
0137 if (ret) {
0138 dev_warn(mdev->dev, "couldn't link PLL to decoder\n");
0139 return ret;
0140 }
0141 } else {
0142 pad_source = media_get_pad_index(tuner, false,
0143 PAD_SIGNAL_ANALOG);
0144 pad_sink = media_get_pad_index(decoder, true,
0145 PAD_SIGNAL_ANALOG);
0146 if (pad_source < 0 || pad_sink < 0) {
0147 dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n",
0148 pad_source, pad_sink);
0149 return -EINVAL;
0150 }
0151 ret = media_create_pad_link(tuner, pad_source,
0152 decoder, pad_sink,
0153 MEDIA_LNK_FL_ENABLED);
0154 if (ret)
0155 return ret;
0156 }
0157
0158 if (if_aud) {
0159 pad_source = media_get_pad_index(tuner, false,
0160 PAD_SIGNAL_AUDIO);
0161 pad_sink = media_get_pad_index(if_aud, true,
0162 PAD_SIGNAL_AUDIO);
0163 if (pad_source < 0 || pad_sink < 0) {
0164 dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n",
0165 pad_source, pad_sink);
0166 return -EINVAL;
0167 }
0168 ret = media_create_pad_link(tuner, pad_source,
0169 if_aud, pad_sink,
0170 MEDIA_LNK_FL_ENABLED);
0171 if (ret) {
0172 dev_warn(mdev->dev, "couldn't link tuner->audio PLL\n");
0173 return ret;
0174 }
0175 } else {
0176 if_aud = tuner;
0177 }
0178
0179 }
0180
0181
0182 if (io_v4l) {
0183 pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
0184 if (pad_source < 0) {
0185 dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n");
0186 return -EINVAL;
0187 }
0188 ret = media_create_pad_link(decoder, pad_source,
0189 io_v4l, 0,
0190 MEDIA_LNK_FL_ENABLED);
0191 if (ret) {
0192 dev_warn(mdev->dev, "couldn't link decoder output to V4L I/O\n");
0193 return ret;
0194 }
0195 }
0196
0197 if (io_swradio) {
0198 pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
0199 if (pad_source < 0) {
0200 dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n");
0201 return -EINVAL;
0202 }
0203 ret = media_create_pad_link(decoder, pad_source,
0204 io_swradio, 0,
0205 MEDIA_LNK_FL_ENABLED);
0206 if (ret) {
0207 dev_warn(mdev->dev, "couldn't link decoder output to SDR\n");
0208 return ret;
0209 }
0210 }
0211
0212 if (io_vbi) {
0213 pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV);
0214 if (pad_source < 0) {
0215 dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n");
0216 return -EINVAL;
0217 }
0218 ret = media_create_pad_link(decoder, pad_source,
0219 io_vbi, 0,
0220 MEDIA_LNK_FL_ENABLED);
0221 if (ret) {
0222 dev_warn(mdev->dev, "couldn't link decoder output to VBI\n");
0223 return ret;
0224 }
0225 }
0226
0227
0228 flags = MEDIA_LNK_FL_ENABLED;
0229 media_device_for_each_entity(entity, mdev) {
0230 switch (entity->function) {
0231 case MEDIA_ENT_F_CONN_RF:
0232 if (!tuner)
0233 continue;
0234 pad_sink = media_get_pad_index(tuner, true,
0235 PAD_SIGNAL_ANALOG);
0236 if (pad_sink < 0) {
0237 dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
0238 return -EINVAL;
0239 }
0240 ret = media_create_pad_link(entity, 0, tuner,
0241 pad_sink,
0242 flags);
0243 break;
0244 case MEDIA_ENT_F_CONN_SVIDEO:
0245 case MEDIA_ENT_F_CONN_COMPOSITE:
0246 pad_sink = media_get_pad_index(decoder, true,
0247 PAD_SIGNAL_ANALOG);
0248 if (pad_sink < 0) {
0249 dev_warn(mdev->dev, "couldn't get decoder analog pad sink\n");
0250 return -EINVAL;
0251 }
0252 ret = media_create_pad_link(entity, 0, decoder,
0253 pad_sink,
0254 flags);
0255 break;
0256 default:
0257 continue;
0258 }
0259 if (ret)
0260 return ret;
0261
0262 flags = 0;
0263 }
0264
0265 return 0;
0266 }
0267 EXPORT_SYMBOL_GPL(v4l2_mc_create_media_graph);
0268
0269 int v4l_enable_media_source(struct video_device *vdev)
0270 {
0271 struct media_device *mdev = vdev->entity.graph_obj.mdev;
0272 int ret = 0, err;
0273
0274 if (!mdev)
0275 return 0;
0276
0277 mutex_lock(&mdev->graph_mutex);
0278 if (!mdev->enable_source)
0279 goto end;
0280 err = mdev->enable_source(&vdev->entity, &vdev->pipe);
0281 if (err)
0282 ret = -EBUSY;
0283 end:
0284 mutex_unlock(&mdev->graph_mutex);
0285 return ret;
0286 }
0287 EXPORT_SYMBOL_GPL(v4l_enable_media_source);
0288
0289 void v4l_disable_media_source(struct video_device *vdev)
0290 {
0291 struct media_device *mdev = vdev->entity.graph_obj.mdev;
0292
0293 if (mdev) {
0294 mutex_lock(&mdev->graph_mutex);
0295 if (mdev->disable_source)
0296 mdev->disable_source(&vdev->entity);
0297 mutex_unlock(&mdev->graph_mutex);
0298 }
0299 }
0300 EXPORT_SYMBOL_GPL(v4l_disable_media_source);
0301
0302 int v4l_vb2q_enable_media_source(struct vb2_queue *q)
0303 {
0304 struct v4l2_fh *fh = q->owner;
0305
0306 if (fh && fh->vdev)
0307 return v4l_enable_media_source(fh->vdev);
0308 return 0;
0309 }
0310 EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
0311
0312 int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
0313 struct media_pad *sink, u32 flags)
0314 {
0315 struct fwnode_handle *endpoint;
0316 struct v4l2_subdev *sink_sd;
0317
0318 if (!(sink->flags & MEDIA_PAD_FL_SINK) ||
0319 !is_media_entity_v4l2_subdev(sink->entity))
0320 return -EINVAL;
0321
0322 sink_sd = media_entity_to_v4l2_subdev(sink->entity);
0323
0324 fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) {
0325 struct fwnode_handle *remote_ep;
0326 int src_idx, sink_idx, ret;
0327 struct media_pad *src;
0328
0329 src_idx = media_entity_get_fwnode_pad(&src_sd->entity,
0330 endpoint,
0331 MEDIA_PAD_FL_SOURCE);
0332 if (src_idx < 0)
0333 continue;
0334
0335 remote_ep = fwnode_graph_get_remote_endpoint(endpoint);
0336 if (!remote_ep)
0337 continue;
0338
0339
0340
0341
0342
0343 sink_idx = media_entity_get_fwnode_pad(&sink_sd->entity,
0344 remote_ep,
0345 MEDIA_PAD_FL_SINK);
0346 fwnode_handle_put(remote_ep);
0347
0348 if (sink_idx < 0 || sink_idx != sink->index)
0349 continue;
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359 src = &src_sd->entity.pads[src_idx];
0360
0361
0362 if (media_entity_find_link(src, sink))
0363 continue;
0364
0365 dev_dbg(sink_sd->dev, "creating link %s:%d -> %s:%d\n",
0366 src_sd->entity.name, src_idx,
0367 sink_sd->entity.name, sink_idx);
0368
0369 ret = media_create_pad_link(&src_sd->entity, src_idx,
0370 &sink_sd->entity, sink_idx, flags);
0371 if (ret) {
0372 dev_err(sink_sd->dev,
0373 "link %s:%d -> %s:%d failed with %d\n",
0374 src_sd->entity.name, src_idx,
0375 sink_sd->entity.name, sink_idx, ret);
0376
0377 fwnode_handle_put(endpoint);
0378 return ret;
0379 }
0380 }
0381
0382 return 0;
0383 }
0384 EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links_to_pad);
0385
0386 int v4l2_create_fwnode_links(struct v4l2_subdev *src_sd,
0387 struct v4l2_subdev *sink_sd)
0388 {
0389 unsigned int i;
0390
0391 for (i = 0; i < sink_sd->entity.num_pads; i++) {
0392 struct media_pad *pad = &sink_sd->entity.pads[i];
0393 int ret;
0394
0395 if (!(pad->flags & MEDIA_PAD_FL_SINK))
0396 continue;
0397
0398 ret = v4l2_create_fwnode_links_to_pad(src_sd, pad, 0);
0399 if (ret)
0400 return ret;
0401 }
0402
0403 return 0;
0404 }
0405 EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links);
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434 static int pipeline_pm_use_count(struct media_entity *entity,
0435 struct media_graph *graph)
0436 {
0437 int use = 0;
0438
0439 media_graph_walk_start(graph, entity);
0440
0441 while ((entity = media_graph_walk_next(graph))) {
0442 if (is_media_entity_v4l2_video_device(entity))
0443 use += entity->use_count;
0444 }
0445
0446 return use;
0447 }
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460 static int pipeline_pm_power_one(struct media_entity *entity, int change)
0461 {
0462 struct v4l2_subdev *subdev;
0463 int ret;
0464
0465 subdev = is_media_entity_v4l2_subdev(entity)
0466 ? media_entity_to_v4l2_subdev(entity) : NULL;
0467
0468 if (entity->use_count == 0 && change > 0 && subdev != NULL) {
0469 ret = v4l2_subdev_call(subdev, core, s_power, 1);
0470 if (ret < 0 && ret != -ENOIOCTLCMD)
0471 return ret;
0472 }
0473
0474 entity->use_count += change;
0475 WARN_ON(entity->use_count < 0);
0476
0477 if (entity->use_count == 0 && change < 0 && subdev != NULL)
0478 v4l2_subdev_call(subdev, core, s_power, 0);
0479
0480 return 0;
0481 }
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493 static int pipeline_pm_power(struct media_entity *entity, int change,
0494 struct media_graph *graph)
0495 {
0496 struct media_entity *first = entity;
0497 int ret = 0;
0498
0499 if (!change)
0500 return 0;
0501
0502 media_graph_walk_start(graph, entity);
0503
0504 while (!ret && (entity = media_graph_walk_next(graph)))
0505 if (is_media_entity_v4l2_subdev(entity))
0506 ret = pipeline_pm_power_one(entity, change);
0507
0508 if (!ret)
0509 return ret;
0510
0511 media_graph_walk_start(graph, first);
0512
0513 while ((first = media_graph_walk_next(graph))
0514 && first != entity)
0515 if (is_media_entity_v4l2_subdev(first))
0516 pipeline_pm_power_one(first, -change);
0517
0518 return ret;
0519 }
0520
0521 static int v4l2_pipeline_pm_use(struct media_entity *entity, unsigned int use)
0522 {
0523 struct media_device *mdev = entity->graph_obj.mdev;
0524 int change = use ? 1 : -1;
0525 int ret;
0526
0527 mutex_lock(&mdev->graph_mutex);
0528
0529
0530 entity->use_count += change;
0531 WARN_ON(entity->use_count < 0);
0532
0533
0534 ret = pipeline_pm_power(entity, change, &mdev->pm_count_walk);
0535 if (ret < 0)
0536 entity->use_count -= change;
0537
0538 mutex_unlock(&mdev->graph_mutex);
0539
0540 return ret;
0541 }
0542
0543 int v4l2_pipeline_pm_get(struct media_entity *entity)
0544 {
0545 return v4l2_pipeline_pm_use(entity, 1);
0546 }
0547 EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_get);
0548
0549 void v4l2_pipeline_pm_put(struct media_entity *entity)
0550 {
0551
0552 WARN_ON(v4l2_pipeline_pm_use(entity, 0));
0553 }
0554 EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_put);
0555
0556 int v4l2_pipeline_link_notify(struct media_link *link, u32 flags,
0557 unsigned int notification)
0558 {
0559 struct media_graph *graph = &link->graph_obj.mdev->pm_count_walk;
0560 struct media_entity *source = link->source->entity;
0561 struct media_entity *sink = link->sink->entity;
0562 int source_use;
0563 int sink_use;
0564 int ret = 0;
0565
0566 source_use = pipeline_pm_use_count(source, graph);
0567 sink_use = pipeline_pm_use_count(sink, graph);
0568
0569 if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
0570 !(flags & MEDIA_LNK_FL_ENABLED)) {
0571
0572 pipeline_pm_power(source, -sink_use, graph);
0573 pipeline_pm_power(sink, -source_use, graph);
0574 return 0;
0575 }
0576
0577 if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH &&
0578 (flags & MEDIA_LNK_FL_ENABLED)) {
0579
0580 ret = pipeline_pm_power(source, sink_use, graph);
0581 if (ret < 0)
0582 return ret;
0583
0584 ret = pipeline_pm_power(sink, source_use, graph);
0585 if (ret < 0)
0586 pipeline_pm_power(source, -sink_use, graph);
0587 }
0588
0589 return ret;
0590 }
0591 EXPORT_SYMBOL_GPL(v4l2_pipeline_link_notify);