From patchwork Tue Feb 14 13:39:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Machek X-Patchwork-Id: 39411 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cddNX-0001c2-AB; Tue, 14 Feb 2017 13:42:47 +0000 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.84_2/mailfrontend-8) with esmtp id 1cddNV-0004H0-jl; Tue, 14 Feb 2017 14:42:47 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754125AbdBNNmW (ORCPT + 1 other); Tue, 14 Feb 2017 08:42:22 -0500 Received: from atrey.karlin.mff.cuni.cz ([195.113.26.193]:59086 "EHLO atrey.karlin.mff.cuni.cz" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753545AbdBNNjz (ORCPT ); Tue, 14 Feb 2017 08:39:55 -0500 Received: by atrey.karlin.mff.cuni.cz (Postfix, from userid 512) id 6F4EB817DB; Tue, 14 Feb 2017 14:39:52 +0100 (CET) Date: Tue, 14 Feb 2017 14:39:51 +0100 From: Pavel Machek To: sakari.ailus@iki.fi Cc: sre@kernel.org, pali.rohar@gmail.com, pavel@ucw.cz, linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, laurent.pinchart@ideasonboard.com, mchehab@kernel.org, ivo.g.dimitrov.75@gmail.com Subject: [RFC 05/13] omap3isp: Add subdevices support Message-ID: <20170214133951.GA8510@amd> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2017.2.14.133617 X-PMX-Spam: Gauge=IIIIIIIII, Probability=9%, Report=' BODY_PARA_IS_SENTENCE_URL 0.1, MULTIPLE_RCPTS 0.1, HTML_00_01 0.05, HTML_00_10 0.05, KNOWN_FREEWEB_URI 0.05, MSGID_ADDED_BY_MTA 0.05, INVALID_MSGID_NO_FQDN 0, LEGITIMATE_SIGNS 0, MULTIPLE_REAL_RCPTS 0, NO_URI_HTTPS 0, URI_ENDS_IN_HTML 0, __ANY_URI 0, __ATTACHMENT_SIZE_0_10K 0, __CD 0, __CP_MEDIA_BODY 0, __CP_URI_IN_BODY 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __FROM_DOMAIN_IN_ANY_CC2 0, __FROM_DOMAIN_IN_RCPT 0, __HAS_ATTACHMENT 0, __HAS_ATTACHMENT1 0, __HAS_ATTACHMENT2 0, __HAS_CC_HDR 0, __HAS_FROM 0, __HAS_LIST_ID 0, __HAS_MSGID 0, __HAS_X_MAILING_LIST 0, __KNOWN_FREEWEB_URI2 0, __MIME_TEXT_P 0, __MIME_TEXT_P1 0, __MIME_TEXT_P2 0, __MIME_VERSION 0, __MULTIPLE_RCPTS_CC_X2 0, __MULTIPLE_URI_TEXT 0, __NO_HTML_TAG_RAW 0, __SANE_MSGID 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_IN_BODY 0, __URI_NS , __URI_WITH_PATH 0, __USER_AGENT 0' Add subdevices support to omap3isp. It is neccessary for connecting subdevices (camera flash and autofocus coil) for N900 camera subsystem. Signed-off-by: Sakari Ailus Signed-off-by: Pavel Machek --- drivers/media/platform/omap3isp/isp.c | 128 ++++++++++++++++++++++------ drivers/media/platform/omap3isp/isp.h | 1 + drivers/media/platform/omap3isp/ispcsiphy.c | 2 +- 3 files changed, 102 insertions(+), 29 deletions(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 61b7359..edc4300 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -42,6 +42,8 @@ * published by the Free Software Foundation. */ +#define DEBUG + #include #include @@ -699,7 +701,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe, spin_unlock_irqrestore(&pipe->lock, flags); pipe->do_propagation = false; - + entity = &pipe->output->video.entity; while (1) { pad = &entity->pads[0]; @@ -2059,7 +2061,7 @@ void __isp_of_parse_node_csi1(struct device *dev, buscfg->vp_clk_pol = 1; } - + static void isp_of_parse_node_csi1(struct device *dev, struct isp_bus_cfg *buscfg, struct v4l2_of_endpoint *vep) @@ -2106,9 +2108,7 @@ static void isp_of_parse_node_csi2(struct device *dev, buscfg->bus.csi2.crc = 1; } -static int isp_endpoint_to_buscfg(struct device *dev, - struct v4l2_of_endpoint vep, - struct isp_bus_cfg *buscfg) +static int isp_endpoint_to_buscfg(struct device *dev, struct v4l2_of_endpoint vep, struct isp_bus_cfg *buscfg) { switch (vep.base.port) { case ISP_OF_PHY_PARALLEL: @@ -2170,10 +2170,51 @@ static int isp_of_parse_node_endpoint(struct device *dev, return 0; } +static int isp_of_parse_node(struct device *dev, struct device_node *node, + struct v4l2_async_notifier *notifier, + u32 group_id, bool link) +{ + struct isp_async_subdev *isd; + + isd = devm_kzalloc(dev, sizeof(*isd), GFP_KERNEL); + if (!isd) { + of_node_put(node); + return -ENOMEM; + } + + notifier->subdevs[notifier->num_subdevs] = &isd->asd; + + if (link) { + if (isp_of_parse_node_endpoint(dev, node, isd)) { + of_node_put(node); + return -EINVAL; + } + + isd->asd.match.of.node = of_graph_get_remote_port_parent(node); + of_node_put(node); + } else { + isd->asd.match.of.node = node; + } + + if (!isd->asd.match.of.node) { + dev_warn(dev, "bad remote port parent\n"); + return -EINVAL; + } + + isd->asd.match_type = V4L2_ASYNC_MATCH_OF; + isd->group_id = group_id; + notifier->num_subdevs++; + + return 0; +} + static int isp_of_parse_nodes(struct device *dev, struct v4l2_async_notifier *notifier) { struct device_node *node = NULL; + int ret; + unsigned int flash = 0; + u32 group_id = 0; notifier->subdevs = devm_kcalloc( dev, ISP_MAX_SUBDEVS, sizeof(*notifier->subdevs), GFP_KERNEL); @@ -2182,32 +2223,60 @@ static int isp_of_parse_nodes(struct device *dev, while (notifier->num_subdevs < ISP_MAX_SUBDEVS && (node = of_graph_get_next_endpoint(dev->of_node, node))) { - struct isp_async_subdev *isd; + ret = isp_of_parse_node(dev, node, notifier, group_id++, true); + if (ret) + return ret; + } - isd = devm_kzalloc(dev, sizeof(*isd), GFP_KERNEL); - if (!isd) - goto error; + while (notifier->num_subdevs < ISP_MAX_SUBDEVS && + (node = of_parse_phandle(dev->of_node, "ti,camera-flashes", + flash++))) { + struct device_node *sensor_node = + of_parse_phandle(dev->of_node, "ti,camera-flashes", + flash++); + unsigned int i; + u32 flash_group_id; - notifier->subdevs[notifier->num_subdevs] = &isd->asd; + if (!sensor_node) + return -EINVAL; - if (isp_of_parse_node_endpoint(dev, node, isd)) - goto error; + for (i = 0; i < notifier->num_subdevs; i++) { + struct isp_async_subdev *isd = container_of( + notifier->subdevs[i], struct isp_async_subdev, + asd); - isd->asd.match.of.node = of_graph_get_remote_port_parent(node); - if (!isd->asd.match.of.node) { - dev_warn(dev, "bad remote port parent\n"); - goto error; + if (!isd->bus) + continue; + + dev_dbg(dev, "match \"%s\", \"%s\"\n",sensor_node->name, + isd->asd.match.of.node->name); + + if (sensor_node != isd->asd.match.of.node) + continue; + + dev_dbg(dev, "found\n"); + + flash_group_id = isd->group_id; + break; } - isd->asd.match_type = V4L2_ASYNC_MATCH_OF; - notifier->num_subdevs++; + /* + * No sensor was found --- complain and allocate a new + * group ID. + */ + if (i == notifier->num_subdevs) { + dev_warn(dev, "no device node \"%s\" was found", + sensor_node->name); + flash_group_id = group_id++; + } + + ret = isp_of_parse_node(dev, node, notifier, flash_group_id, + false); + if (ret) + return ret; } return notifier->num_subdevs; - -error: - of_node_put(node); - return -EINVAL; } static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async, @@ -2218,7 +2287,7 @@ static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async, container_of(asd, struct isp_async_subdev, asd); isd->sd = subdev; - isd->sd->host_priv = &isd->bus; + isd->sd->host_priv = isd->bus; return 0; } @@ -2421,12 +2490,15 @@ static int isp_probe(struct platform_device *pdev) if (ret < 0) goto error_register_entities; - isp->notifier.bound = isp_subdev_notifier_bound; - isp->notifier.complete = isp_subdev_notifier_complete; + if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { + isp->notifier.bound = isp_subdev_notifier_bound; + isp->notifier.complete = isp_subdev_notifier_complete; - ret = v4l2_async_notifier_register(&isp->v4l2_dev, &isp->notifier); - if (ret) - goto error_register_entities; + ret = v4l2_async_notifier_register(&isp->v4l2_dev, + &isp->notifier); + if (ret) + goto error_register_entities; + } isp_core_init(isp, 1); omap3isp_put(isp); diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index c0b9d1d..639b3ca 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -230,6 +230,7 @@ struct isp_async_subdev { struct v4l2_subdev *sd; struct isp_bus_cfg *bus; struct v4l2_async_subdev asd; + u32 group_id; }; #define v4l2_dev_to_isp_device(dev) \ diff --git a/drivers/media/platform/omap3isp/ispcsiphy.c b/drivers/media/platform/omap3isp/ispcsiphy.c index 871d4fe..6b814e1 100644 --- a/drivers/media/platform/omap3isp/ispcsiphy.c +++ b/drivers/media/platform/omap3isp/ispcsiphy.c @@ -177,7 +177,7 @@ static int omap3isp_csiphy_config(struct isp_csiphy *phy) struct isp_async_subdev *isd = container_of(pipe->external->asd, struct isp_async_subdev, asd); - buscfg = &isd->bus; + buscfg = isd->bus; } if (buscfg->interface == ISP_INTERFACE_CCP2B_PHY1