Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] s5p-fimc: Use v4l2_subdev internal ops to register video nodes

In order to be able to select only FIMC-LITE support, which is added
with subsequent patches, the regular FIMC support is now contained
only in fimc-core.c, fimc-m2m.c and fimc-capture.c files. The graph
and pipeline management is now solely handled in fimc-mdevice.[ch].
This means the FIMC driver can now be excluded with Kconfig option,
leaving only FIMC-LITE and allowing this driver to be reused in SoCs
that have only FIMC-LITE and no regular FIMC IP.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Sylwester Nawrocki and committed by
Mauro Carvalho Chehab
693f5c40 97d97422

+138 -131
+77 -65
drivers/media/video/s5p-fimc/fimc-capture.c
··· 993 993 if (!(pad->flags & MEDIA_PAD_FL_SINK)) 994 994 break; 995 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 997 struct fimc_frame *ff = &vid_cap->ctx->s_frame; 998 998 sink_fmt.format.width = ff->f_width; 999 999 sink_fmt.format.height = ff->f_height; ··· 1489 1489 .pad = &fimc_subdev_pad_ops, 1490 1490 }; 1491 1491 1492 - static 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; 1520 - sd_err: 1521 - media_entity_cleanup(&sd->entity); 1522 - me_err: 1523 - kfree(sd); 1524 - return ret; 1525 - } 1526 - 1527 - static 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 1492 /* Set default format at the sensor and host interface */ 1540 1493 static int fimc_capture_set_default_format(struct fimc_dev *fimc) 1541 1494 { ··· 1507 1554 } 1508 1555 1509 1556 /* fimc->lock must be already initialized */ 1510 - int fimc_register_capture_device(struct fimc_dev *fimc, 1557 + static int fimc_register_capture_device(struct fimc_dev *fimc, 1511 1558 struct v4l2_device *v4l2_dev) 1512 1559 { 1513 1560 struct video_device *vfd; ··· 1525 1572 ctx->out_path = FIMC_DMA; 1526 1573 ctx->state = FIMC_CTX_CAP; 1527 1574 ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); 1528 - ctx->d_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); 1575 + ctx->d_frame.fmt = ctx->s_frame.fmt; 1529 1576 1530 1577 vfd = video_device_alloc(); 1531 1578 if (!vfd) { ··· 1533 1580 goto err_vd_alloc; 1534 1581 } 1535 1582 1536 - snprintf(vfd->name, sizeof(vfd->name), "%s.capture", 1537 - dev_name(&fimc->pdev->dev)); 1583 + snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.capture", fimc->id); 1538 1584 1539 1585 vfd->fops = &fimc_capture_fops; 1540 1586 vfd->ioctl_ops = &fimc_capture_ioctl_ops; ··· 1568 1616 1569 1617 vb2_queue_init(q); 1570 1618 1571 - fimc->vid_cap.vd_pad.flags = MEDIA_PAD_FL_SINK; 1572 - ret = media_entity_init(&vfd->entity, 1, &fimc->vid_cap.vd_pad, 0); 1619 + vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; 1620 + ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); 1573 1621 if (ret) 1574 1622 goto err_ent; 1575 - ret = fimc_create_capture_subdev(fimc, v4l2_dev); 1623 + 1624 + ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); 1576 1625 if (ret) 1577 - goto err_sd_reg; 1626 + goto err_vd; 1627 + 1628 + v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n", 1629 + vfd->name, video_device_node_name(vfd)); 1578 1630 1579 1631 vfd->ctrl_handler = &ctx->ctrl_handler; 1580 1632 return 0; 1581 1633 1582 - err_sd_reg: 1634 + err_vd: 1583 1635 media_entity_cleanup(&vfd->entity); 1584 1636 err_ent: 1585 1637 video_device_release(vfd); ··· 1592 1636 return ret; 1593 1637 } 1594 1638 1595 - void fimc_unregister_capture_device(struct fimc_dev *fimc) 1639 + static int fimc_capture_subdev_registered(struct v4l2_subdev *sd) 1596 1640 { 1597 - struct video_device *vfd = fimc->vid_cap.vfd; 1641 + struct fimc_dev *fimc = v4l2_get_subdevdata(sd); 1642 + int ret; 1598 1643 1599 - if (vfd) { 1600 - media_entity_cleanup(&vfd->entity); 1601 - /* Can also be called if video device was 1602 - not registered */ 1603 - video_unregister_device(vfd); 1644 + ret = fimc_register_m2m_device(fimc, sd->v4l2_dev); 1645 + if (ret) 1646 + return ret; 1647 + 1648 + ret = fimc_register_capture_device(fimc, sd->v4l2_dev); 1649 + if (ret) 1650 + fimc_unregister_m2m_device(fimc); 1651 + 1652 + return ret; 1653 + } 1654 + 1655 + static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) 1656 + { 1657 + struct fimc_dev *fimc = v4l2_get_subdevdata(sd); 1658 + 1659 + if (fimc == NULL) 1660 + return; 1661 + 1662 + fimc_unregister_m2m_device(fimc); 1663 + 1664 + if (fimc->vid_cap.vfd) { 1665 + media_entity_cleanup(&fimc->vid_cap.vfd->entity); 1666 + video_unregister_device(fimc->vid_cap.vfd); 1667 + fimc->vid_cap.vfd = NULL; 1604 1668 } 1605 - fimc_destroy_capture_subdev(fimc); 1669 + 1606 1670 kfree(fimc->vid_cap.ctx); 1607 1671 fimc->vid_cap.ctx = NULL; 1672 + } 1673 + 1674 + static const struct v4l2_subdev_internal_ops fimc_capture_sd_internal_ops = { 1675 + .registered = fimc_capture_subdev_registered, 1676 + .unregistered = fimc_capture_subdev_unregistered, 1677 + }; 1678 + 1679 + int fimc_initialize_capture_subdev(struct fimc_dev *fimc) 1680 + { 1681 + struct v4l2_subdev *sd = &fimc->vid_cap.subdev; 1682 + int ret; 1683 + 1684 + v4l2_subdev_init(sd, &fimc_subdev_ops); 1685 + sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; 1686 + snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id); 1687 + 1688 + fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 1689 + fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; 1690 + ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM, 1691 + fimc->vid_cap.sd_pads, 0); 1692 + if (ret) 1693 + return ret; 1694 + 1695 + sd->entity.ops = &fimc_sd_media_ops; 1696 + sd->internal_ops = &fimc_capture_sd_internal_ops; 1697 + v4l2_set_subdevdata(sd, fimc); 1698 + return 0; 1699 + } 1700 + 1701 + void fimc_unregister_capture_subdev(struct fimc_dev *fimc) 1702 + { 1703 + struct v4l2_subdev *sd = &fimc->vid_cap.subdev; 1704 + 1705 + v4l2_device_unregister_subdev(sd); 1706 + media_entity_cleanup(&sd->entity); 1707 + v4l2_set_subdevdata(sd, NULL); 1608 1708 }
+9 -4
drivers/media/video/s5p-fimc/fimc-core.c
··· 842 842 clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); 843 843 clk_enable(fimc->clock[CLK_BUS]); 844 844 845 - platform_set_drvdata(pdev, fimc); 846 - 847 845 ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler, 848 846 0, pdev->name, fimc); 849 847 if (ret) { ··· 849 851 goto err_clk; 850 852 } 851 853 854 + ret = fimc_initialize_capture_subdev(fimc); 855 + if (ret) 856 + goto err_clk; 857 + 858 + platform_set_drvdata(pdev, fimc); 852 859 pm_runtime_enable(&pdev->dev); 853 860 ret = pm_runtime_get_sync(&pdev->dev); 854 861 if (ret < 0) 855 - goto err_clk; 862 + goto err_sd; 856 863 /* Initialize contiguous memory allocator */ 857 864 fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); 858 865 if (IS_ERR(fimc->alloc_ctx)) { ··· 869 866 870 867 pm_runtime_put(&pdev->dev); 871 868 return 0; 872 - 873 869 err_pm: 874 870 pm_runtime_put(&pdev->dev); 871 + err_sd: 872 + fimc_unregister_capture_subdev(fimc); 875 873 err_clk: 876 874 fimc_clk_put(fimc); 877 875 return ret; ··· 957 953 pm_runtime_disable(&pdev->dev); 958 954 pm_runtime_set_suspended(&pdev->dev); 959 955 956 + fimc_unregister_capture_subdev(fimc); 960 957 vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); 961 958 962 959 clk_disable(fimc->clock[CLK_BUS]);
+3 -4
drivers/media/video/s5p-fimc/fimc-core.h
··· 331 331 struct fimc_ctx *ctx; 332 332 struct vb2_alloc_ctx *alloc_ctx; 333 333 struct video_device *vfd; 334 - struct v4l2_subdev *subdev; 334 + struct v4l2_subdev subdev; 335 335 struct media_pad vd_pad; 336 336 struct v4l2_mbus_framefmt mf; 337 337 struct media_pad sd_pads[FIMC_SD_PADS_NUM]; ··· 737 737 738 738 /* -----------------------------------------------------*/ 739 739 /* fimc-capture.c */ 740 - int fimc_register_capture_device(struct fimc_dev *fimc, 741 - struct v4l2_device *v4l2_dev); 742 - void fimc_unregister_capture_device(struct fimc_dev *fimc); 740 + int fimc_initialize_capture_subdev(struct fimc_dev *fimc); 741 + void fimc_unregister_capture_subdev(struct fimc_dev *fimc); 743 742 int fimc_capture_ctrls_create(struct fimc_dev *fimc); 744 743 void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification, 745 744 void *arg);
+14 -3
drivers/media/video/s5p-fimc/fimc-m2m.c
··· 776 776 This driver needs auditing so that this flag can be removed. */ 777 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 780 video_set_drvdata(vfd, fimc); 781 781 782 782 fimc->m2m.vfd = vfd; ··· 788 788 } 789 789 790 790 ret = media_entity_init(&vfd->entity, 0, NULL, 0); 791 - if (!ret) 792 - return 0; 791 + if (ret) 792 + goto err_me; 793 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; 801 + 802 + err_vd: 803 + media_entity_cleanup(&vfd->entity); 804 + err_me: 794 805 v4l2_m2m_release(fimc->m2m.m2m_dev); 795 806 err_init: 796 807 video_device_release(fimc->m2m.vfd);
+34 -55
drivers/media/video/s5p-fimc/fimc-mdevice.c
··· 304 304 static int fimc_register_callback(struct device *dev, void *p) 305 305 { 306 306 struct fimc_dev *fimc = dev_get_drvdata(dev); 307 + struct v4l2_subdev *sd = &fimc->vid_cap.subdev; 307 308 struct fimc_md *fmd = p; 308 - int ret; 309 + int ret = 0; 309 310 310 311 if (!fimc || !fimc->pdev) 311 312 return 0; ··· 314 313 return 0; 315 314 316 315 fmd->fimc[fimc->pdev->id] = fimc; 317 - ret = fimc_register_m2m_device(fimc, &fmd->v4l2_dev); 318 - if (ret) 319 - return ret; 320 - ret = fimc_register_capture_device(fimc, &fmd->v4l2_dev); 321 - if (!ret) 322 - fimc->vid_cap.user_subdev_api = fmd->user_subdev_api; 316 + sd->grp_id = FIMC_GROUP_ID; 317 + 318 + ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); 319 + if (ret) { 320 + v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n", 321 + fimc->id, ret); 322 + } 323 + 323 324 return ret; 324 325 } 325 326 ··· 404 401 for (i = 0; i < FIMC_MAX_DEVS; i++) { 405 402 if (fmd->fimc[i] == NULL) 406 403 continue; 407 - fimc_unregister_m2m_device(fmd->fimc[i]); 408 - fimc_unregister_capture_device(fmd->fimc[i]); 404 + v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev); 409 405 fmd->fimc[i] = NULL; 410 406 } 411 407 for (i = 0; i < CSIS_MAX_ENTITIES; i++) { ··· 420 418 fimc_md_unregister_sensor(fmd->sensor[i].subdev); 421 419 fmd->sensor[i].subdev = NULL; 422 420 } 423 - } 424 - 425 - static int fimc_md_register_video_nodes(struct fimc_md *fmd) 426 - { 427 - struct video_device *vdev; 428 - int i, ret = 0; 429 - 430 - for (i = 0; i < FIMC_MAX_DEVS && !ret; i++) { 431 - if (!fmd->fimc[i]) 432 - continue; 433 - 434 - vdev = fmd->fimc[i]->m2m.vfd; 435 - if (vdev) { 436 - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); 437 - if (ret) 438 - break; 439 - v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n", 440 - vdev->name, video_device_node_name(vdev)); 441 - } 442 - 443 - vdev = fmd->fimc[i]->vid_cap.vfd; 444 - if (vdev == NULL) 445 - continue; 446 - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); 447 - v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n", 448 - vdev->name, video_device_node_name(vdev)); 449 - } 450 - 451 - return ret; 452 421 } 453 422 454 423 /** ··· 452 479 continue; 453 480 454 481 flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0; 455 - sink = &fmd->fimc[i]->vid_cap.subdev->entity; 482 + sink = &fmd->fimc[i]->vid_cap.subdev.entity; 456 483 ret = media_entity_create_link(source, pad, sink, 457 484 FIMC_SD_PAD_SINK, flags); 458 485 if (ret) ··· 561 588 for (i = 0; i < FIMC_MAX_DEVS; i++) { 562 589 if (!fmd->fimc[i]) 563 590 continue; 564 - source = &fmd->fimc[i]->vid_cap.subdev->entity; 591 + source = &fmd->fimc[i]->vid_cap.subdev.entity; 565 592 sink = &fmd->fimc[i]->vid_cap.vfd->entity; 566 593 ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, 567 594 sink, 0, flags); ··· 790 817 ret = media_device_register(&fmd->media_dev); 791 818 if (ret < 0) { 792 819 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret); 793 - goto err2; 820 + goto err_md; 794 821 } 795 822 ret = fimc_md_get_clocks(fmd); 796 823 if (ret) 797 - goto err3; 824 + goto err_clk; 798 825 799 826 fmd->user_subdev_api = false; 827 + 828 + /* Protect the media graph while we're registering entities */ 829 + mutex_lock(&fmd->media_dev.graph_mutex); 830 + 800 831 ret = fimc_md_register_platform_entities(fmd); 801 832 if (ret) 802 - goto err3; 833 + goto err_unlock; 803 834 804 835 if (pdev->dev.platform_data) { 805 836 ret = fimc_md_register_sensor_entities(fmd); 806 837 if (ret) 807 - goto err3; 838 + goto err_unlock; 808 839 } 809 840 ret = fimc_md_create_links(fmd); 810 841 if (ret) 811 - goto err3; 842 + goto err_unlock; 812 843 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); 813 844 if (ret) 814 - goto err3; 815 - ret = fimc_md_register_video_nodes(fmd); 816 - if (ret) 817 - goto err3; 845 + goto err_unlock; 818 846 819 847 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); 820 - if (!ret) { 821 - platform_set_drvdata(pdev, fmd); 822 - return 0; 823 - } 824 - err3: 848 + if (ret) 849 + goto err_unlock; 850 + 851 + platform_set_drvdata(pdev, fmd); 852 + mutex_unlock(&fmd->media_dev.graph_mutex); 853 + return 0; 854 + 855 + err_unlock: 856 + mutex_unlock(&fmd->media_dev.graph_mutex); 857 + err_clk: 825 858 media_device_unregister(&fmd->media_dev); 826 859 fimc_md_put_clocks(fmd); 827 860 fimc_md_unregister_entities(fmd); 828 - err2: 861 + err_md: 829 862 v4l2_device_unregister(&fmd->v4l2_dev); 830 863 return ret; 831 864 }
+1
drivers/media/video/s5p-fimc/fimc-mdevice.h
··· 24 24 #define SENSOR_GROUP_ID (1 << 8) 25 25 #define CSIS_GROUP_ID (1 << 9) 26 26 #define WRITEBACK_GROUP_ID (1 << 10) 27 + #define FIMC_GROUP_ID (1 << 11) 27 28 28 29 #define FIMC_MAX_SENSORS 8 29 30 #define FIMC_MAX_CAMCLKS 2