aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLad, Prabhakar <prabhakar.csengg@gmail.com>2013-06-25 10:17:35 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-07-26 12:17:15 -0400
commit4b8a531e6bb0686203e9cf82a54dfe189de7d5c2 (patch)
tree92972e6a269e42f1bb7baa06aa8cc38e31b65be2
parent873229e4fdf34196aa5d707957c59ba54c25eaba (diff)
[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>
-rw-r--r--drivers/media/platform/davinci/vpif_display.c210
-rw-r--r--drivers/media/platform/davinci/vpif_display.h3
-rw-r--r--include/media/davinci/vpif_types.h2
3 files changed, 132 insertions, 83 deletions
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index e6e573650250..c2ff06745fdc 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -1618,6 +1618,102 @@ vpif_init_free_channel_objects:
1618 return err; 1618 return err;
1619} 1619}
1620 1620
1621static 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
1638static 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
1702probe_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
1712static int vpif_async_complete(struct v4l2_async_notifier *notifier)
1713{
1714 return vpif_probe_complete();
1715}
1716
1621/* 1717/*
1622 * vpif_probe: This function creates device entries by register itself to the 1718 * vpif_probe: This function creates device entries by register itself to the
1623 * V4L2 driver and initializes fields of each channel objects 1719 * V4L2 driver and initializes fields of each channel objects
@@ -1625,11 +1721,9 @@ vpif_init_free_channel_objects:
1625static __init int vpif_probe(struct platform_device *pdev) 1721static __init int vpif_probe(struct platform_device *pdev)
1626{ 1722{
1627 struct vpif_subdev_info *subdevdata; 1723 struct vpif_subdev_info *subdevdata;
1628 struct vpif_display_config *config; 1724 int i, j = 0, err = 0;
1629 int i, j = 0, k, err = 0;
1630 int res_idx = 0; 1725 int res_idx = 0;
1631 struct i2c_adapter *i2c_adap; 1726 struct i2c_adapter *i2c_adap;
1632 struct common_obj *common;
1633 struct channel_obj *ch; 1727 struct channel_obj *ch;
1634 struct video_device *vfd; 1728 struct video_device *vfd;
1635 struct resource *res; 1729 struct resource *res;
@@ -1708,11 +1802,9 @@ static __init int vpif_probe(struct platform_device *pdev)
1708 size/2; 1802 size/2;
1709 } 1803 }
1710 } 1804 }
1711 1805 vpif_obj.config = pdev->dev.platform_data;
1712 i2c_adap = i2c_get_adapter(1); 1806 subdev_count = vpif_obj.config->subdev_count;
1713 config = pdev->dev.platform_data; 1807 subdevdata = vpif_obj.config->subdevinfo;
1714 subdev_count = config->subdev_count;
1715 subdevdata = config->subdevinfo;
1716 vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, 1808 vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
1717 GFP_KERNEL); 1809 GFP_KERNEL);
1718 if (vpif_obj.sd == NULL) { 1810 if (vpif_obj.sd == NULL) {
@@ -1721,86 +1813,40 @@ static __init int vpif_probe(struct platform_device *pdev)
1721 goto vpif_sd_error; 1813 goto vpif_sd_error;
1722 } 1814 }
1723 1815
1724 for (i = 0; i < subdev_count; i++) { 1816 if (!vpif_obj.config->asd_sizes) {
1725 vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, 1817 i2c_adap = i2c_get_adapter(1);
1726 i2c_adap, 1818 for (i = 0; i < subdev_count; i++) {
1727 &subdevdata[i].board_info, 1819 vpif_obj.sd[i] =
1728 NULL); 1820 v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
1729 if (!vpif_obj.sd[i]) { 1821 i2c_adap,
1730 vpif_err("Error registering v4l2 subdevice\n"); 1822 &subdevdata[i].
1731 err = -ENODEV; 1823 board_info,
1732 goto probe_subdev_out; 1824 NULL);
1733 } 1825 if (!vpif_obj.sd[i]) {
1734 1826 vpif_err("Error registering v4l2 subdevice\n");
1735 if (vpif_obj.sd[i]) 1827 goto probe_subdev_out;
1736 vpif_obj.sd[i]->grp_id = 1 << i; 1828 }
1737 }
1738
1739 for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
1740 ch = vpif_obj.dev[j];
1741 /* Initialize field of the channel objects */
1742 atomic_set(&ch->usrs, 0);
1743 for (k = 0; k < VPIF_NUMOBJECTS; k++) {
1744 ch->common[k].numbuffers = 0;
1745 common = &ch->common[k];
1746 common->io_usrs = 0;
1747 common->started = 0;
1748 spin_lock_init(&common->irqlock);
1749 mutex_init(&common->lock);
1750 common->numbuffers = 0;
1751 common->set_addr = NULL;
1752 common->ytop_off = common->ybtm_off = 0;
1753 common->ctop_off = common->cbtm_off = 0;
1754 common->cur_frm = common->next_frm = NULL;
1755 memset(&common->fmt, 0, sizeof(common->fmt));
1756 common->numbuffers = config_params.numbuffers[k];
1757 1829
1830 if (vpif_obj.sd[i])
1831 vpif_obj.sd[i]->grp_id = 1 << i;
1832 }
1833 vpif_probe_complete();
1834 } else {
1835 vpif_obj.notifier.subdev = vpif_obj.config->asd;
1836 vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
1837 vpif_obj.notifier.bound = vpif_async_bound;
1838 vpif_obj.notifier.complete = vpif_async_complete;
1839 err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
1840 &vpif_obj.notifier);
1841 if (err) {
1842 vpif_err("Error registering async notifier\n");
1843 err = -EINVAL;
1844 goto probe_subdev_out;
1758 } 1845 }
1759 ch->initialized = 0;
1760 if (subdev_count)
1761 ch->sd = vpif_obj.sd[0];
1762 ch->channel_id = j;
1763 if (j < 2)
1764 ch->common[VPIF_VIDEO_INDEX].numbuffers =
1765 config_params.numbuffers[ch->channel_id];
1766 else
1767 ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;
1768
1769 memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
1770
1771 /* Initialize prio member of channel object */
1772 v4l2_prio_init(&ch->prio);
1773 ch->common[VPIF_VIDEO_INDEX].fmt.type =
1774 V4L2_BUF_TYPE_VIDEO_OUTPUT;
1775 ch->video_dev->lock = &common->lock;
1776 video_set_drvdata(ch->video_dev, ch);
1777
1778 /* select output 0 */
1779 err = vpif_set_output(config, ch, 0);
1780 if (err)
1781 goto probe_out;
1782
1783 /* register video device */
1784 vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
1785 (int)ch, (int)&ch->video_dev);
1786
1787 err = video_register_device(ch->video_dev,
1788 VFL_TYPE_GRABBER, (j ? 3 : 2));
1789 if (err < 0)
1790 goto probe_out;
1791 } 1846 }
1792 1847
1793 v4l2_info(&vpif_obj.v4l2_dev,
1794 " VPIF display driver initialized\n");
1795 return 0; 1848 return 0;
1796 1849
1797probe_out:
1798 for (k = 0; k < j; k++) {
1799 ch = vpif_obj.dev[k];
1800 video_unregister_device(ch->video_dev);
1801 video_device_release(ch->video_dev);
1802 ch->video_dev = NULL;
1803 }
1804probe_subdev_out: 1850probe_subdev_out:
1805 kfree(vpif_obj.sd); 1851 kfree(vpif_obj.sd);
1806vpif_sd_error: 1852vpif_sd_error:
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h
index 5d87fc86e580..4d0485b99a80 100644
--- a/drivers/media/platform/davinci/vpif_display.h
+++ b/drivers/media/platform/davinci/vpif_display.h
@@ -148,7 +148,8 @@ struct vpif_device {
148 struct v4l2_device v4l2_dev; 148 struct v4l2_device v4l2_dev;
149 struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS]; 149 struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS];
150 struct v4l2_subdev **sd; 150 struct v4l2_subdev **sd;
151 151 struct v4l2_async_notifier notifier;
152 struct vpif_display_config *config;
152}; 153};
153 154
154struct vpif_config_params { 155struct vpif_config_params {
diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h
index e08bcde52d05..3cb1704a0650 100644
--- a/include/media/davinci/vpif_types.h
+++ b/include/media/davinci/vpif_types.h
@@ -59,6 +59,8 @@ struct vpif_display_config {
59 int subdev_count; 59 int subdev_count;
60 struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS]; 60 struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
61 const char *card_name; 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
64struct vpif_input { 66struct vpif_input {