From patchwork Wed Dec 28 18:31:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Machek X-Patchwork-Id: 38834 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cMJAW-0006Yq-UI; Wed, 28 Dec 2016 18:41:44 +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-5) with esmtp id 1cMJAU-00089W-8n; Wed, 28 Dec 2016 19:41:44 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751850AbcL1SlX (ORCPT + 1 other); Wed, 28 Dec 2016 13:41:23 -0500 Received: from atrey.karlin.mff.cuni.cz ([195.113.26.193]:49678 "EHLO atrey.karlin.mff.cuni.cz" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751446AbcL1SlW (ORCPT ); Wed, 28 Dec 2016 13:41:22 -0500 Received: by atrey.karlin.mff.cuni.cz (Postfix, from userid 512) id 81670824B3; Wed, 28 Dec 2016 19:31:16 +0100 (CET) Date: Wed, 28 Dec 2016 19:31:16 +0100 From: Pavel Machek To: sakari.ailus@iki.fi, sre@kernel.org, pali.rohar@gmail.com, pavel@ucw.cz, linux-media@vger.kernel.org, kernel list Subject: [PATCH] v4l: add support for CSI-1 bus Message-ID: <20161228183116.GA13407@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: 2016.12.28.183316 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, BODY_SIZE_6000_6999 0, BODY_SIZE_7000_LESS 0, INVALID_MSGID_NO_FQDN 0, LEGITIMATE_NEGATE 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, __FRAUD_BODY_WEBMAIL 0, __FRAUD_WEBMAIL 0, __FROM_DOMAIN_IN_ANY_TO2 0, __FROM_DOMAIN_IN_RCPT 0, __HAS_ATTACHMENT 0, __HAS_ATTACHMENT1 0, __HAS_ATTACHMENT2 0, __HAS_FROM 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_TO_X5 0, __MULTIPLE_URI_TEXT 0, __NO_HTML_TAG_RAW 0, __SANE_MSGID 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __TO_NAME 0, __TO_NAME_DIFF_FROM_ACC 0, __TO_NO_NAME 0, __TO_REAL_NAMES 0, __URI_IN_BODY 0, __URI_NS , __URI_WITH_PATH 0, __USER_AGENT 0' From: Sakari Ailus The function to parse CSI2 bus parameters was called v4l2_of_parse_csi_bus(), rename it as v4l2_of_parse_csi2_bus() in anticipation of CSI1/CCP2 support. Obtain data bus type from bus-type property. Only try parsing bus specific properties in this case. Add CSI1 and CCP2 bus type to enum v4l2_mbus_type. CCP2, or CSI-1, is an older single data lane serial bus. Separate lane parsing from CSI-2 bus parameter parsing. The CSI-1 will need these as well, separate them into a different function. have_clk_lane and num_data_lanes arguments may be NULL; the CSI-1 bus will have no use for them. Signed-off-by: Sakari Ailus Signed-off-by: Ivaylo Dimitrov Signed-off-by: Pavel Machek diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c index 93b3368..60bbc5f 100644 --- a/drivers/media/v4l2-core/v4l2-of.c +++ b/drivers/media/v4l2-core/v4l2-of.c @@ -20,53 +20,88 @@ #include -static int v4l2_of_parse_csi_bus(const struct device_node *node, - struct v4l2_of_endpoint *endpoint) +enum v4l2_of_bus_type { + V4L2_OF_BUS_TYPE_CSI2 = 0, + V4L2_OF_BUS_TYPE_PARALLEL, +}; + +static int v4l2_of_parse_lanes(const struct device_node *node, + unsigned char *clock_lane, + bool *have_clk_lane, + unsigned char *data_lanes, + bool *lane_polarities, + unsigned short *__num_data_lanes, + unsigned int max_data_lanes) { - struct v4l2_of_bus_mipi_csi2 *bus = &endpoint->bus.mipi_csi2; struct property *prop; - bool have_clk_lane = false; - unsigned int flags = 0; + unsigned short num_data_lanes = 0; u32 v; prop = of_find_property(node, "data-lanes", NULL); if (prop) { const __be32 *lane = NULL; - unsigned int i; - for (i = 0; i < ARRAY_SIZE(bus->data_lanes); i++) { + for (num_data_lanes = 0; num_data_lanes < max_data_lanes; + num_data_lanes++) { lane = of_prop_next_u32(prop, lane, &v); if (!lane) break; - bus->data_lanes[i] = v; + data_lanes[num_data_lanes] = v; } - bus->num_data_lanes = i; } + if (__num_data_lanes) + *__num_data_lanes = num_data_lanes; prop = of_find_property(node, "lane-polarities", NULL); if (prop) { const __be32 *polarity = NULL; unsigned int i; - for (i = 0; i < ARRAY_SIZE(bus->lane_polarities); i++) { + for (i = 0; i < 1 + max_data_lanes; i++) { polarity = of_prop_next_u32(prop, polarity, &v); if (!polarity) break; - bus->lane_polarities[i] = v; + lane_polarities[i] = v; } - if (i < 1 + bus->num_data_lanes /* clock + data */) { + if (i < 1 + num_data_lanes /* clock + data */) { pr_warn("%s: too few lane-polarities entries (need %u, got %u)\n", - node->full_name, 1 + bus->num_data_lanes, i); + node->full_name, 1 + num_data_lanes, i); return -EINVAL; } } + if (have_clk_lane) + *have_clk_lane = false; + if (!of_property_read_u32(node, "clock-lanes", &v)) { - bus->clock_lane = v; - have_clk_lane = true; + *clock_lane = v; + if (have_clk_lane) + *have_clk_lane = true; } + return 0; +} + +static int v4l2_of_parse_csi2_bus(const struct device_node *node, + struct v4l2_of_endpoint *endpoint) +{ + struct v4l2_of_bus_mipi_csi2 *bus = &endpoint->bus.mipi_csi2; + bool have_clk_lane = false; + unsigned int flags = 0; + int rval; + u32 v; + + rval = v4l2_of_parse_lanes(node, &bus->clock_lane, &have_clk_lane, + bus->data_lanes, bus->lane_polarities, + &bus->num_data_lanes, + ARRAY_SIZE(bus->data_lanes)); + if (rval) + return rval; + + BUILD_BUG_ON(1 + ARRAY_SIZE(bus->data_lanes) + != ARRAY_SIZE(bus->lane_polarities)); + if (of_get_property(node, "clock-noncontinuous", &v)) flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK; else if (have_clk_lane || bus->num_data_lanes > 0) @@ -151,6 +186,7 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node, int v4l2_of_parse_endpoint(const struct device_node *node, struct v4l2_of_endpoint *endpoint) { + u32 bus_type; int rval; of_graph_parse_endpoint(node, &endpoint->base); @@ -158,17 +194,33 @@ int v4l2_of_parse_endpoint(const struct device_node *node, memset(&endpoint->bus_type, 0, sizeof(*endpoint) - offsetof(typeof(*endpoint), bus_type)); - rval = v4l2_of_parse_csi_bus(node, endpoint); - if (rval) - return rval; - /* - * Parse the parallel video bus properties only if none - * of the MIPI CSI-2 specific properties were found. - */ - if (endpoint->bus.mipi_csi2.flags == 0) - v4l2_of_parse_parallel_bus(node, endpoint); + rval = of_property_read_u32(node, "bus-type", &bus_type); + if (rval < 0) { + endpoint->bus_type = 0; + rval = v4l2_of_parse_csi2_bus(node, endpoint); + if (rval) + return rval; + /* + * Parse the parallel video bus properties only if none + * of the MIPI CSI-2 specific properties were found. + */ + if (endpoint->bus.mipi_csi2.flags == 0) + v4l2_of_parse_parallel_bus(node, endpoint); + + return 0; + } - return 0; + switch (bus_type) { + case V4L2_OF_BUS_TYPE_CSI2: + return v4l2_of_parse_csi2_bus(node, endpoint); + case V4L2_OF_BUS_TYPE_PARALLEL: + v4l2_of_parse_parallel_bus(node, endpoint); + return 0; + default: + pr_warn("bad bus-type %u, device_node \"%s\"\n", + bus_type, node->full_name); + return -EINVAL; + } } EXPORT_SYMBOL(v4l2_of_parse_endpoint); diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h index 34cc99e..315c167 100644 --- a/include/media/v4l2-mediabus.h +++ b/include/media/v4l2-mediabus.h @@ -69,11 +69,15 @@ * @V4L2_MBUS_PARALLEL: parallel interface with hsync and vsync * @V4L2_MBUS_BT656: parallel interface with embedded synchronisation, can * also be used for BT.1120 + * @V4L2_MBUS_CSI1: MIPI CSI-1 serial interface + * @V4L2_MBUS_CCP2: CCP2 (Compact Camera Port 2) * @V4L2_MBUS_CSI2: MIPI CSI-2 serial interface */ enum v4l2_mbus_type { V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656, + V4L2_MBUS_CSI1, + V4L2_MBUS_CCP2, V4L2_MBUS_CSI2, };