aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c142
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c13
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h7
-rw-r--r--drivers/media/video/s5p-fimc/fimc-m2m.c17
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.c89
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.h1
6 files changed, 138 insertions, 131 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 0051d8161c6c..b45da2780213 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -993,7 +993,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
993 if (!(pad->flags & MEDIA_PAD_FL_SINK)) 993 if (!(pad->flags & MEDIA_PAD_FL_SINK))
994 break; 994 break;
995 /* Don't call FIMC subdev operation to avoid nested locking */ 995 /* Don't call FIMC subdev operation to avoid nested locking */
996 if (sd == fimc->vid_cap.subdev) { 996 if (sd == &fimc->vid_cap.subdev) {
997 struct fimc_frame *ff = &vid_cap->ctx->s_frame; 997 struct fimc_frame *ff = &vid_cap->ctx->s_frame;
998 sink_fmt.format.width = ff->f_width; 998 sink_fmt.format.width = ff->f_width;
999 sink_fmt.format.height = ff->f_height; 999 sink_fmt.format.height = ff->f_height;
@@ -1489,53 +1489,6 @@ static struct v4l2_subdev_ops fimc_subdev_ops = {
1489 .pad = &fimc_subdev_pad_ops, 1489 .pad = &fimc_subdev_pad_ops,
1490}; 1490};
1491 1491
1492static int fimc_create_capture_subdev(struct fimc_dev *fimc,
1493 struct v4l2_device *v4l2_dev)
1494{
1495 struct v4l2_subdev *sd;
1496 int ret;
1497
1498 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
1499 if (!sd)
1500 return -ENOMEM;
1501
1502 v4l2_subdev_init(sd, &fimc_subdev_ops);
1503 sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
1504 snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id);
1505
1506 fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1507 fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1508 ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
1509 fimc->vid_cap.sd_pads, 0);
1510 if (ret)
1511 goto me_err;
1512 ret = v4l2_device_register_subdev(v4l2_dev, sd);
1513 if (ret)
1514 goto sd_err;
1515
1516 fimc->vid_cap.subdev = sd;
1517 v4l2_set_subdevdata(sd, fimc);
1518 sd->entity.ops = &fimc_sd_media_ops;
1519 return 0;
1520sd_err:
1521 media_entity_cleanup(&sd->entity);
1522me_err:
1523 kfree(sd);
1524 return ret;
1525}
1526
1527static void fimc_destroy_capture_subdev(struct fimc_dev *fimc)
1528{
1529 struct v4l2_subdev *sd = fimc->vid_cap.subdev;
1530
1531 if (!sd)
1532 return;
1533 media_entity_cleanup(&sd->entity);
1534 v4l2_device_unregister_subdev(sd);
1535 kfree(sd);
1536 fimc->vid_cap.subdev = NULL;
1537}
1538
1539/* Set default format at the sensor and host interface */ 1492/* Set default format at the sensor and host interface */
1540static int fimc_capture_set_default_format(struct fimc_dev *fimc) 1493static int fimc_capture_set_default_format(struct fimc_dev *fimc)
1541{ 1494{
@@ -1554,7 +1507,7 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc)
1554} 1507}
1555 1508
1556/* fimc->lock must be already initialized */ 1509/* fimc->lock must be already initialized */
1557int fimc_register_capture_device(struct fimc_dev *fimc, 1510static int fimc_register_capture_device(struct fimc_dev *fimc,
1558 struct v4l2_device *v4l2_dev) 1511 struct v4l2_device *v4l2_dev)
1559{ 1512{
1560 struct video_device *vfd; 1513 struct video_device *vfd;
@@ -1572,7 +1525,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc,
1572 ctx->out_path = FIMC_DMA; 1525 ctx->out_path = FIMC_DMA;
1573 ctx->state = FIMC_CTX_CAP; 1526 ctx->state = FIMC_CTX_CAP;
1574 ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); 1527 ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
1575 ctx->d_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); 1528 ctx->d_frame.fmt = ctx->s_frame.fmt;
1576 1529
1577 vfd = video_device_alloc(); 1530 vfd = video_device_alloc();
1578 if (!vfd) { 1531 if (!vfd) {
@@ -1580,8 +1533,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc,
1580 goto err_vd_alloc; 1533 goto err_vd_alloc;
1581 } 1534 }
1582 1535
1583 snprintf(vfd->name, sizeof(vfd->name), "%s.capture", 1536 snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.capture", fimc->id);
1584 dev_name(&fimc->pdev->dev));
1585 1537
1586 vfd->fops = &fimc_capture_fops; 1538 vfd->fops = &fimc_capture_fops;
1587 vfd->ioctl_ops = &fimc_capture_ioctl_ops; 1539 vfd->ioctl_ops = &fimc_capture_ioctl_ops;
@@ -1616,18 +1568,22 @@ int fimc_register_capture_device(struct fimc_dev *fimc,
1616 1568
1617 vb2_queue_init(q); 1569 vb2_queue_init(q);
1618 1570
1619 fimc->vid_cap.vd_pad.flags = MEDIA_PAD_FL_SINK; 1571 vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK;
1620 ret = media_entity_init(&vfd->entity, 1, &fimc->vid_cap.vd_pad, 0); 1572 ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0);
1621 if (ret) 1573 if (ret)
1622 goto err_ent; 1574 goto err_ent;
1623 ret = fimc_create_capture_subdev(fimc, v4l2_dev); 1575
1576 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1624 if (ret) 1577 if (ret)
1625 goto err_sd_reg; 1578 goto err_vd;
1579
1580 v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
1581 vfd->name, video_device_node_name(vfd));
1626 1582
1627 vfd->ctrl_handler = &ctx->ctrl_handler; 1583 vfd->ctrl_handler = &ctx->ctrl_handler;
1628 return 0; 1584 return 0;
1629 1585
1630err_sd_reg: 1586err_vd:
1631 media_entity_cleanup(&vfd->entity); 1587 media_entity_cleanup(&vfd->entity);
1632err_ent: 1588err_ent:
1633 video_device_release(vfd); 1589 video_device_release(vfd);
@@ -1636,17 +1592,73 @@ err_vd_alloc:
1636 return ret; 1592 return ret;
1637} 1593}
1638 1594
1639void fimc_unregister_capture_device(struct fimc_dev *fimc) 1595static int fimc_capture_subdev_registered(struct v4l2_subdev *sd)
1640{ 1596{
1641 struct video_device *vfd = fimc->vid_cap.vfd; 1597 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1598 int ret;
1642 1599
1643 if (vfd) { 1600 ret = fimc_register_m2m_device(fimc, sd->v4l2_dev);
1644 media_entity_cleanup(&vfd->entity); 1601 if (ret)
1645 /* Can also be called if video device was 1602 return ret;
1646 not registered */ 1603
1647 video_unregister_device(vfd); 1604 ret = fimc_register_capture_device(fimc, sd->v4l2_dev);
1605 if (ret)
1606 fimc_unregister_m2m_device(fimc);
1607
1608 return ret;
1609}
1610
1611static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd)
1612{
1613 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1614
1615 if (fimc == NULL)
1616 return;
1617
1618 fimc_unregister_m2m_device(fimc);
1619
1620 if (fimc->vid_cap.vfd) {
1621 media_entity_cleanup(&fimc->vid_cap.vfd->entity);
1622 video_unregister_device(fimc->vid_cap.vfd);
1623 fimc->vid_cap.vfd = NULL;
1648 } 1624 }
1649 fimc_destroy_capture_subdev(fimc); 1625
1650 kfree(fimc->vid_cap.ctx); 1626 kfree(fimc->vid_cap.ctx);
1651 fimc->vid_cap.ctx = NULL; 1627 fimc->vid_cap.ctx = NULL;
1652} 1628}
1629
1630static const struct v4l2_subdev_internal_ops fimc_capture_sd_internal_ops = {
1631 .registered = fimc_capture_subdev_registered,
1632 .unregistered = fimc_capture_subdev_unregistered,
1633};
1634
1635int fimc_initialize_capture_subdev(struct fimc_dev *fimc)
1636{
1637 struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
1638 int ret;
1639
1640 v4l2_subdev_init(sd, &fimc_subdev_ops);
1641 sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
1642 snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id);
1643
1644 fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1645 fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1646 ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
1647 fimc->vid_cap.sd_pads, 0);
1648 if (ret)
1649 return ret;
1650
1651 sd->entity.ops = &fimc_sd_media_ops;
1652 sd->internal_ops = &fimc_capture_sd_internal_ops;
1653 v4l2_set_subdevdata(sd, fimc);
1654 return 0;
1655}
1656
1657void fimc_unregister_capture_subdev(struct fimc_dev *fimc)
1658{
1659 struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
1660
1661 v4l2_device_unregister_subdev(sd);
1662 media_entity_cleanup(&sd->entity);
1663 v4l2_set_subdevdata(sd, NULL);
1664}
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 749db4deefcb..add24cd373a5 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -842,8 +842,6 @@ static int fimc_probe(struct platform_device *pdev)
842 clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); 842 clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
843 clk_enable(fimc->clock[CLK_BUS]); 843 clk_enable(fimc->clock[CLK_BUS]);
844 844
845 platform_set_drvdata(pdev, fimc);
846
847 ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler, 845 ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler,
848 0, pdev->name, fimc); 846 0, pdev->name, fimc);
849 if (ret) { 847 if (ret) {
@@ -851,10 +849,15 @@ static int fimc_probe(struct platform_device *pdev)
851 goto err_clk; 849 goto err_clk;
852 } 850 }
853 851
852 ret = fimc_initialize_capture_subdev(fimc);
853 if (ret)
854 goto err_clk;
855
856 platform_set_drvdata(pdev, fimc);
854 pm_runtime_enable(&pdev->dev); 857 pm_runtime_enable(&pdev->dev);
855 ret = pm_runtime_get_sync(&pdev->dev); 858 ret = pm_runtime_get_sync(&pdev->dev);
856 if (ret < 0) 859 if (ret < 0)
857 goto err_clk; 860 goto err_sd;
858 /* Initialize contiguous memory allocator */ 861 /* Initialize contiguous memory allocator */
859 fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); 862 fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
860 if (IS_ERR(fimc->alloc_ctx)) { 863 if (IS_ERR(fimc->alloc_ctx)) {
@@ -866,9 +869,10 @@ static int fimc_probe(struct platform_device *pdev)
866 869
867 pm_runtime_put(&pdev->dev); 870 pm_runtime_put(&pdev->dev);
868 return 0; 871 return 0;
869
870err_pm: 872err_pm:
871 pm_runtime_put(&pdev->dev); 873 pm_runtime_put(&pdev->dev);
874err_sd:
875 fimc_unregister_capture_subdev(fimc);
872err_clk: 876err_clk:
873 fimc_clk_put(fimc); 877 fimc_clk_put(fimc);
874 return ret; 878 return ret;
@@ -953,6 +957,7 @@ static int __devexit fimc_remove(struct platform_device *pdev)
953 pm_runtime_disable(&pdev->dev); 957 pm_runtime_disable(&pdev->dev);
954 pm_runtime_set_suspended(&pdev->dev); 958 pm_runtime_set_suspended(&pdev->dev);
955 959
960 fimc_unregister_capture_subdev(fimc);
956 vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); 961 vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
957 962
958 clk_disable(fimc->clock[CLK_BUS]); 963 clk_disable(fimc->clock[CLK_BUS]);
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 288631a86e53..ef7c6a23ca2a 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -331,7 +331,7 @@ struct fimc_vid_cap {
331 struct fimc_ctx *ctx; 331 struct fimc_ctx *ctx;
332 struct vb2_alloc_ctx *alloc_ctx; 332 struct vb2_alloc_ctx *alloc_ctx;
333 struct video_device *vfd; 333 struct video_device *vfd;
334 struct v4l2_subdev *subdev; 334 struct v4l2_subdev subdev;
335 struct media_pad vd_pad; 335 struct media_pad vd_pad;
336 struct v4l2_mbus_framefmt mf; 336 struct v4l2_mbus_framefmt mf;
337 struct media_pad sd_pads[FIMC_SD_PADS_NUM]; 337 struct media_pad sd_pads[FIMC_SD_PADS_NUM];
@@ -737,9 +737,8 @@ void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state);
737 737
738/* -----------------------------------------------------*/ 738/* -----------------------------------------------------*/
739/* fimc-capture.c */ 739/* fimc-capture.c */
740int fimc_register_capture_device(struct fimc_dev *fimc, 740int fimc_initialize_capture_subdev(struct fimc_dev *fimc);
741 struct v4l2_device *v4l2_dev); 741void fimc_unregister_capture_subdev(struct fimc_dev *fimc);
742void fimc_unregister_capture_device(struct fimc_dev *fimc);
743int fimc_capture_ctrls_create(struct fimc_dev *fimc); 742int fimc_capture_ctrls_create(struct fimc_dev *fimc);
744void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification, 743void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
745 void *arg); 744 void *arg);
diff --git a/drivers/media/video/s5p-fimc/fimc-m2m.c b/drivers/media/video/s5p-fimc/fimc-m2m.c
index 9935cc4bd0cb..92b6059b25bf 100644
--- a/drivers/media/video/s5p-fimc/fimc-m2m.c
+++ b/drivers/media/video/s5p-fimc/fimc-m2m.c
@@ -776,7 +776,7 @@ int fimc_register_m2m_device(struct fimc_dev *fimc,
776 This driver needs auditing so that this flag can be removed. */ 776 This driver needs auditing so that this flag can be removed. */
777 set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); 777 set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
778 778
779 snprintf(vfd->name, sizeof(vfd->name), "%s.m2m", dev_name(&pdev->dev)); 779 snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id);
780 video_set_drvdata(vfd, fimc); 780 video_set_drvdata(vfd, fimc);
781 781
782 fimc->m2m.vfd = vfd; 782 fimc->m2m.vfd = vfd;
@@ -788,9 +788,20 @@ int fimc_register_m2m_device(struct fimc_dev *fimc,
788 } 788 }
789 789
790 ret = media_entity_init(&vfd->entity, 0, NULL, 0); 790 ret = media_entity_init(&vfd->entity, 0, NULL, 0);
791 if (!ret) 791 if (ret)
792 return 0; 792 goto err_me;
793
794 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
795 if (ret)
796 goto err_vd;
797
798 v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
799 vfd->name, video_device_node_name(vfd));
800 return 0;
793 801
802err_vd:
803 media_entity_cleanup(&vfd->entity);
804err_me:
794 v4l2_m2m_release(fimc->m2m.m2m_dev); 805 v4l2_m2m_release(fimc->m2m.m2m_dev);
795err_init: 806err_init:
796 video_device_release(fimc->m2m.vfd); 807 video_device_release(fimc->m2m.vfd);
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
index f97ac02b8677..c319842c762d 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
@@ -304,8 +304,9 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
304static int fimc_register_callback(struct device *dev, void *p) 304static int fimc_register_callback(struct device *dev, void *p)
305{ 305{
306 struct fimc_dev *fimc = dev_get_drvdata(dev); 306 struct fimc_dev *fimc = dev_get_drvdata(dev);
307 struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
307 struct fimc_md *fmd = p; 308 struct fimc_md *fmd = p;
308 int ret; 309 int ret = 0;
309 310
310 if (!fimc || !fimc->pdev) 311 if (!fimc || !fimc->pdev)
311 return 0; 312 return 0;
@@ -313,12 +314,14 @@ static int fimc_register_callback(struct device *dev, void *p)
313 return 0; 314 return 0;
314 315
315 fmd->fimc[fimc->pdev->id] = fimc; 316 fmd->fimc[fimc->pdev->id] = fimc;
316 ret = fimc_register_m2m_device(fimc, &fmd->v4l2_dev); 317 sd->grp_id = FIMC_GROUP_ID;
317 if (ret) 318
318 return ret; 319 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
319 ret = fimc_register_capture_device(fimc, &fmd->v4l2_dev); 320 if (ret) {
320 if (!ret) 321 v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
321 fimc->vid_cap.user_subdev_api = fmd->user_subdev_api; 322 fimc->id, ret);
323 }
324
322 return ret; 325 return ret;
323} 326}
324 327
@@ -401,8 +404,7 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
401 for (i = 0; i < FIMC_MAX_DEVS; i++) { 404 for (i = 0; i < FIMC_MAX_DEVS; i++) {
402 if (fmd->fimc[i] == NULL) 405 if (fmd->fimc[i] == NULL)
403 continue; 406 continue;
404 fimc_unregister_m2m_device(fmd->fimc[i]); 407 v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev);
405 fimc_unregister_capture_device(fmd->fimc[i]);
406 fmd->fimc[i] = NULL; 408 fmd->fimc[i] = NULL;
407 } 409 }
408 for (i = 0; i < CSIS_MAX_ENTITIES; i++) { 410 for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
@@ -420,35 +422,6 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
420 } 422 }
421} 423}
422 424
423static int fimc_md_register_video_nodes(struct fimc_md *fmd)
424{
425 struct video_device *vdev;
426 int i, ret = 0;
427
428 for (i = 0; i < FIMC_MAX_DEVS && !ret; i++) {
429 if (!fmd->fimc[i])
430 continue;
431
432 vdev = fmd->fimc[i]->m2m.vfd;
433 if (vdev) {
434 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
435 if (ret)
436 break;
437 v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n",
438 vdev->name, video_device_node_name(vdev));
439 }
440
441 vdev = fmd->fimc[i]->vid_cap.vfd;
442 if (vdev == NULL)
443 continue;
444 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
445 v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n",
446 vdev->name, video_device_node_name(vdev));
447 }
448
449 return ret;
450}
451
452/** 425/**
453 * __fimc_md_create_fimc_links - create links to all FIMC entities 426 * __fimc_md_create_fimc_links - create links to all FIMC entities
454 * @fmd: fimc media device 427 * @fmd: fimc media device
@@ -479,7 +452,7 @@ static int __fimc_md_create_fimc_links(struct fimc_md *fmd,
479 continue; 452 continue;
480 453
481 flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0; 454 flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
482 sink = &fmd->fimc[i]->vid_cap.subdev->entity; 455 sink = &fmd->fimc[i]->vid_cap.subdev.entity;
483 ret = media_entity_create_link(source, pad, sink, 456 ret = media_entity_create_link(source, pad, sink,
484 FIMC_SD_PAD_SINK, flags); 457 FIMC_SD_PAD_SINK, flags);
485 if (ret) 458 if (ret)
@@ -588,7 +561,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
588 for (i = 0; i < FIMC_MAX_DEVS; i++) { 561 for (i = 0; i < FIMC_MAX_DEVS; i++) {
589 if (!fmd->fimc[i]) 562 if (!fmd->fimc[i])
590 continue; 563 continue;
591 source = &fmd->fimc[i]->vid_cap.subdev->entity; 564 source = &fmd->fimc[i]->vid_cap.subdev.entity;
592 sink = &fmd->fimc[i]->vid_cap.vfd->entity; 565 sink = &fmd->fimc[i]->vid_cap.vfd->entity;
593 ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, 566 ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
594 sink, 0, flags); 567 sink, 0, flags);
@@ -817,42 +790,48 @@ static int fimc_md_probe(struct platform_device *pdev)
817 ret = media_device_register(&fmd->media_dev); 790 ret = media_device_register(&fmd->media_dev);
818 if (ret < 0) { 791 if (ret < 0) {
819 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret); 792 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
820 goto err2; 793 goto err_md;
821 } 794 }
822 ret = fimc_md_get_clocks(fmd); 795 ret = fimc_md_get_clocks(fmd);
823 if (ret) 796 if (ret)
824 goto err3; 797 goto err_clk;
825 798
826 fmd->user_subdev_api = false; 799 fmd->user_subdev_api = false;
800
801 /* Protect the media graph while we're registering entities */
802 mutex_lock(&fmd->media_dev.graph_mutex);
803
827 ret = fimc_md_register_platform_entities(fmd); 804 ret = fimc_md_register_platform_entities(fmd);
828 if (ret) 805 if (ret)
829 goto err3; 806 goto err_unlock;
830 807
831 if (pdev->dev.platform_data) { 808 if (pdev->dev.platform_data) {
832 ret = fimc_md_register_sensor_entities(fmd); 809 ret = fimc_md_register_sensor_entities(fmd);
833 if (ret) 810 if (ret)
834 goto err3; 811 goto err_unlock;
835 } 812 }
836 ret = fimc_md_create_links(fmd); 813 ret = fimc_md_create_links(fmd);
837 if (ret) 814 if (ret)
838 goto err3; 815 goto err_unlock;
839 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); 816 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
840 if (ret) 817 if (ret)
841 goto err3; 818 goto err_unlock;
842 ret = fimc_md_register_video_nodes(fmd);
843 if (ret)
844 goto err3;
845 819
846 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); 820 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
847 if (!ret) { 821 if (ret)
848 platform_set_drvdata(pdev, fmd); 822 goto err_unlock;
849 return 0; 823
850 } 824 platform_set_drvdata(pdev, fmd);
851err3: 825 mutex_unlock(&fmd->media_dev.graph_mutex);
826 return 0;
827
828err_unlock:
829 mutex_unlock(&fmd->media_dev.graph_mutex);
830err_clk:
852 media_device_unregister(&fmd->media_dev); 831 media_device_unregister(&fmd->media_dev);
853 fimc_md_put_clocks(fmd); 832 fimc_md_put_clocks(fmd);
854 fimc_md_unregister_entities(fmd); 833 fimc_md_unregister_entities(fmd);
855err2: 834err_md:
856 v4l2_device_unregister(&fmd->v4l2_dev); 835 v4l2_device_unregister(&fmd->v4l2_dev);
857 return ret; 836 return ret;
858} 837}
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.h b/drivers/media/video/s5p-fimc/fimc-mdevice.h
index da3780823e7d..4f3b69c682cb 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.h
@@ -24,6 +24,7 @@
24#define SENSOR_GROUP_ID (1 << 8) 24#define SENSOR_GROUP_ID (1 << 8)
25#define CSIS_GROUP_ID (1 << 9) 25#define CSIS_GROUP_ID (1 << 9)
26#define WRITEBACK_GROUP_ID (1 << 10) 26#define WRITEBACK_GROUP_ID (1 << 10)
27#define FIMC_GROUP_ID (1 << 11)
27 28
28#define FIMC_MAX_SENSORS 8 29#define FIMC_MAX_SENSORS 8
29#define FIMC_MAX_CAMCLKS 2 30#define FIMC_MAX_CAMCLKS 2