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

[media] media: davinci: vpif: display: add V4L2-async support

Add support for asynchronous subdevice probing, using the v4l2-async API.
The legacy synchronous mode is still supported too, which allows to
gradually update drivers and platforms.

Signed-off-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Sakari Ailus <sakari.ailus@iki.fi>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>

authored by

Lad, Prabhakar and committed by
Mauro Carvalho Chehab
4b8a531e 873229e4

+132 -83
+128 -82
drivers/media/platform/davinci/vpif_display.c
··· 1618 1618 return err; 1619 1619 } 1620 1620 1621 + static int vpif_async_bound(struct v4l2_async_notifier *notifier, 1622 + struct v4l2_subdev *subdev, 1623 + struct v4l2_async_subdev *asd) 1624 + { 1625 + int i; 1626 + 1627 + for (i = 0; i < vpif_obj.config->subdev_count; i++) 1628 + if (!strcmp(vpif_obj.config->subdevinfo[i].name, 1629 + subdev->name)) { 1630 + vpif_obj.sd[i] = subdev; 1631 + vpif_obj.sd[i]->grp_id = 1 << i; 1632 + return 0; 1633 + } 1634 + 1635 + return -EINVAL; 1636 + } 1637 + 1638 + static int vpif_probe_complete(void) 1639 + { 1640 + struct common_obj *common; 1641 + struct channel_obj *ch; 1642 + int j, err, k; 1643 + 1644 + for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { 1645 + ch = vpif_obj.dev[j]; 1646 + /* Initialize field of the channel objects */ 1647 + atomic_set(&ch->usrs, 0); 1648 + for (k = 0; k < VPIF_NUMOBJECTS; k++) { 1649 + ch->common[k].numbuffers = 0; 1650 + common = &ch->common[k]; 1651 + common->io_usrs = 0; 1652 + common->started = 0; 1653 + spin_lock_init(&common->irqlock); 1654 + mutex_init(&common->lock); 1655 + common->numbuffers = 0; 1656 + common->set_addr = NULL; 1657 + common->ytop_off = 0; 1658 + common->ybtm_off = 0; 1659 + common->ctop_off = 0; 1660 + common->cbtm_off = 0; 1661 + common->cur_frm = NULL; 1662 + common->next_frm = NULL; 1663 + memset(&common->fmt, 0, sizeof(common->fmt)); 1664 + common->numbuffers = config_params.numbuffers[k]; 1665 + } 1666 + ch->initialized = 0; 1667 + if (vpif_obj.config->subdev_count) 1668 + ch->sd = vpif_obj.sd[0]; 1669 + ch->channel_id = j; 1670 + if (j < 2) 1671 + ch->common[VPIF_VIDEO_INDEX].numbuffers = 1672 + config_params.numbuffers[ch->channel_id]; 1673 + else 1674 + ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; 1675 + 1676 + memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); 1677 + 1678 + /* Initialize prio member of channel object */ 1679 + v4l2_prio_init(&ch->prio); 1680 + ch->common[VPIF_VIDEO_INDEX].fmt.type = 1681 + V4L2_BUF_TYPE_VIDEO_OUTPUT; 1682 + ch->video_dev->lock = &common->lock; 1683 + video_set_drvdata(ch->video_dev, ch); 1684 + 1685 + /* select output 0 */ 1686 + err = vpif_set_output(vpif_obj.config, ch, 0); 1687 + if (err) 1688 + goto probe_out; 1689 + 1690 + /* register video device */ 1691 + vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", 1692 + (int)ch, (int)&ch->video_dev); 1693 + 1694 + err = video_register_device(ch->video_dev, 1695 + VFL_TYPE_GRABBER, (j ? 3 : 2)); 1696 + if (err < 0) 1697 + goto probe_out; 1698 + } 1699 + 1700 + return 0; 1701 + 1702 + probe_out: 1703 + for (k = 0; k < j; k++) { 1704 + ch = vpif_obj.dev[k]; 1705 + video_unregister_device(ch->video_dev); 1706 + video_device_release(ch->video_dev); 1707 + ch->video_dev = NULL; 1708 + } 1709 + return err; 1710 + } 1711 + 1712 + static int vpif_async_complete(struct v4l2_async_notifier *notifier) 1713 + { 1714 + return vpif_probe_complete(); 1715 + } 1716 + 1621 1717 /* 1622 1718 * vpif_probe: This function creates device entries by register itself to the 1623 1719 * V4L2 driver and initializes fields of each channel objects ··· 1721 1625 static __init int vpif_probe(struct platform_device *pdev) 1722 1626 { 1723 1627 struct vpif_subdev_info *subdevdata; 1724 - struct vpif_display_config *config; 1725 - int i, j = 0, k, err = 0; 1628 + int i, j = 0, err = 0; 1726 1629 int res_idx = 0; 1727 1630 struct i2c_adapter *i2c_adap; 1728 - struct common_obj *common; 1729 1631 struct channel_obj *ch; 1730 1632 struct video_device *vfd; 1731 1633 struct resource *res; ··· 1802 1708 size/2; 1803 1709 } 1804 1710 } 1805 - 1806 - i2c_adap = i2c_get_adapter(1); 1807 - config = pdev->dev.platform_data; 1808 - subdev_count = config->subdev_count; 1809 - subdevdata = config->subdevinfo; 1711 + vpif_obj.config = pdev->dev.platform_data; 1712 + subdev_count = vpif_obj.config->subdev_count; 1713 + subdevdata = vpif_obj.config->subdevinfo; 1810 1714 vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, 1811 1715 GFP_KERNEL); 1812 1716 if (vpif_obj.sd == NULL) { ··· 1813 1721 goto vpif_sd_error; 1814 1722 } 1815 1723 1816 - for (i = 0; i < subdev_count; i++) { 1817 - vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, 1818 - i2c_adap, 1819 - &subdevdata[i].board_info, 1820 - NULL); 1821 - if (!vpif_obj.sd[i]) { 1822 - vpif_err("Error registering v4l2 subdevice\n"); 1823 - err = -ENODEV; 1724 + if (!vpif_obj.config->asd_sizes) { 1725 + i2c_adap = i2c_get_adapter(1); 1726 + for (i = 0; i < subdev_count; i++) { 1727 + vpif_obj.sd[i] = 1728 + v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, 1729 + i2c_adap, 1730 + &subdevdata[i]. 1731 + board_info, 1732 + NULL); 1733 + if (!vpif_obj.sd[i]) { 1734 + vpif_err("Error registering v4l2 subdevice\n"); 1735 + goto probe_subdev_out; 1736 + } 1737 + 1738 + if (vpif_obj.sd[i]) 1739 + vpif_obj.sd[i]->grp_id = 1 << i; 1740 + } 1741 + vpif_probe_complete(); 1742 + } else { 1743 + vpif_obj.notifier.subdev = vpif_obj.config->asd; 1744 + vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; 1745 + vpif_obj.notifier.bound = vpif_async_bound; 1746 + vpif_obj.notifier.complete = vpif_async_complete; 1747 + err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, 1748 + &vpif_obj.notifier); 1749 + if (err) { 1750 + vpif_err("Error registering async notifier\n"); 1751 + err = -EINVAL; 1824 1752 goto probe_subdev_out; 1825 1753 } 1826 - 1827 - if (vpif_obj.sd[i]) 1828 - vpif_obj.sd[i]->grp_id = 1 << i; 1829 1754 } 1830 1755 1831 - for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { 1832 - ch = vpif_obj.dev[j]; 1833 - /* Initialize field of the channel objects */ 1834 - atomic_set(&ch->usrs, 0); 1835 - for (k = 0; k < VPIF_NUMOBJECTS; k++) { 1836 - ch->common[k].numbuffers = 0; 1837 - common = &ch->common[k]; 1838 - common->io_usrs = 0; 1839 - common->started = 0; 1840 - spin_lock_init(&common->irqlock); 1841 - mutex_init(&common->lock); 1842 - common->numbuffers = 0; 1843 - common->set_addr = NULL; 1844 - common->ytop_off = common->ybtm_off = 0; 1845 - common->ctop_off = common->cbtm_off = 0; 1846 - common->cur_frm = common->next_frm = NULL; 1847 - memset(&common->fmt, 0, sizeof(common->fmt)); 1848 - common->numbuffers = config_params.numbuffers[k]; 1849 - 1850 - } 1851 - ch->initialized = 0; 1852 - if (subdev_count) 1853 - ch->sd = vpif_obj.sd[0]; 1854 - ch->channel_id = j; 1855 - if (j < 2) 1856 - ch->common[VPIF_VIDEO_INDEX].numbuffers = 1857 - config_params.numbuffers[ch->channel_id]; 1858 - else 1859 - ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; 1860 - 1861 - memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); 1862 - 1863 - /* Initialize prio member of channel object */ 1864 - v4l2_prio_init(&ch->prio); 1865 - ch->common[VPIF_VIDEO_INDEX].fmt.type = 1866 - V4L2_BUF_TYPE_VIDEO_OUTPUT; 1867 - ch->video_dev->lock = &common->lock; 1868 - video_set_drvdata(ch->video_dev, ch); 1869 - 1870 - /* select output 0 */ 1871 - err = vpif_set_output(config, ch, 0); 1872 - if (err) 1873 - goto probe_out; 1874 - 1875 - /* register video device */ 1876 - vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", 1877 - (int)ch, (int)&ch->video_dev); 1878 - 1879 - err = video_register_device(ch->video_dev, 1880 - VFL_TYPE_GRABBER, (j ? 3 : 2)); 1881 - if (err < 0) 1882 - goto probe_out; 1883 - } 1884 - 1885 - v4l2_info(&vpif_obj.v4l2_dev, 1886 - " VPIF display driver initialized\n"); 1887 1756 return 0; 1888 1757 1889 - probe_out: 1890 - for (k = 0; k < j; k++) { 1891 - ch = vpif_obj.dev[k]; 1892 - video_unregister_device(ch->video_dev); 1893 - video_device_release(ch->video_dev); 1894 - ch->video_dev = NULL; 1895 - } 1896 1758 probe_subdev_out: 1897 1759 kfree(vpif_obj.sd); 1898 1760 vpif_sd_error:
+2 -1
drivers/media/platform/davinci/vpif_display.h
··· 148 148 struct v4l2_device v4l2_dev; 149 149 struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS]; 150 150 struct v4l2_subdev **sd; 151 - 151 + struct v4l2_async_notifier notifier; 152 + struct vpif_display_config *config; 152 153 }; 153 154 154 155 struct vpif_config_params {
+2
include/media/davinci/vpif_types.h
··· 59 59 int subdev_count; 60 60 struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS]; 61 61 const char *card_name; 62 + struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ 63 + int *asd_sizes; /* 0-terminated array of asd group sizes */ 62 64 }; 63 65 64 66 struct vpif_input {