From patchwork Mon Mar 9 10:14:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203629 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A592C18E5A for ; Mon, 9 Mar 2020 10:14:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F139C24677 for ; Mon, 9 Mar 2020 10:14:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726467AbgCIKOp (ORCPT ); Mon, 9 Mar 2020 06:14:45 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:59313 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725796AbgCIKOp (ORCPT ); Mon, 9 Mar 2020 06:14:45 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQj-0003mL-6t; Mon, 09 Mar 2020 11:14:37 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQg-0001le-Ks; Mon, 09 Mar 2020 11:14:34 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org, Rob Herring Subject: [PATCH v12 01/19] dt-bindings: connector: analog: add sdtv standards property Date: Mon, 9 Mar 2020 11:14:10 +0100 Message-Id: <20200309101428.15267-2-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Some connectors no matter if in- or output supports only a limited range of sdtv standards. It doesn't matter if the hardware behind that connector supports more than the listed formats since the users are restriced by a label e.g. to plug only a camera into this connector which uses the PAL format. This patch adds the capability to describe such limitation within the firmware. There are no format restrictions if the property isn't present, so it's completely backward compatible. Signed-off-by: Marco Felsch Reviewed-by: Rob Herring --- [1] https://patchwork.kernel.org/cover/10794703/ v12: - split patch https://patchwork.linuxtv.org/patch/58491/ v10: - fix typo s/TV_STD_*/SDTV_STD_*/ v8: Hi Rob, I dropped your r b tag becuase of the changes I made in this version. Please can you have look on it again? Luckily this would be the last time ;-) - move definition to include/dt-bindings/display - rename tvnorms.h to sdtv-standards.h - TVORMS_* -> SDTV_STD_* - add sync comments - adapt commit message - fix bindings documentation v7: I kept Robs r b tag because I only changed the example and extended TVNORM_* macros. - fix some style issues - add TVNORM_NTSC, TVNORM_525_60 and TVNORM_625_50 v6: - tvnorms.h: use tabs instead of spaces - tvnorms.h: add TVNORM_PAL and TVNORM_SECAM - tvnorms.h: drop rarely used TVNORM_ATSC_* norms v2-v4: - nothing since the patch was squashed from series [1] into this series. .../bindings/display/connector/analog-tv-connector.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt b/Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt index 0c0970c210ab..883bcb2604c7 100644 --- a/Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt +++ b/Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt @@ -6,16 +6,22 @@ Required properties: Optional properties: - label: a symbolic name for the connector +- sdtv-standards: limit the supported TV standards on a connector to the given + ones. If not specified all TV standards are allowed. + Possible TV standards are defined in + include/dt-bindings/display/sdtv-standards.h. Required nodes: - Video port for TV input Example ------- +#include tv: connector { compatible = "composite-video-connector"; label = "tv"; + sdtv-standards = <(SDTV_STD_PAL | SDTV_STD_NTSC)>; port { tv_connector_in: endpoint { From patchwork Mon Mar 9 10:14:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203626 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36987C18E7A for ; Mon, 9 Mar 2020 10:14:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1B0642072A for ; Mon, 9 Mar 2020 10:14:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726640AbgCIKO4 (ORCPT ); Mon, 9 Mar 2020 06:14:56 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:60005 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726490AbgCIKOu (ORCPT ); Mon, 9 Mar 2020 06:14:50 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQj-0003mN-63; Mon, 09 Mar 2020 11:14:37 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQg-0001lk-MG; Mon, 09 Mar 2020 11:14:34 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org Subject: [PATCH v12 03/19] media: v4l: link dt-bindings and uapi Date: Mon, 9 Mar 2020 11:14:12 +0100 Message-Id: <20200309101428.15267-4-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Since we expose the definition to the dt-bindings we need to keep those definitions in sync. To address this the patch adds a simple cross reference to the dt-bindings. Signed-off-by: Marco Felsch --- Changelog: v11: - new patch since the split https://patchwork.linuxtv.org/patch/58491/ v2-v10: - nothing --- include/uapi/linux/videodev2.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 5f9357dcb060..f48e47e230c3 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1242,6 +1242,10 @@ struct v4l2_selection { typedef __u64 v4l2_std_id; +/* + * Attention: Keep the V4L2_STD_* bit definitions in sync with + * include/dt-bindings/display/sdtv-standards.h SDTV_STD_* bit definitions. + */ /* one bit for each */ #define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001) #define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002) From patchwork Mon Mar 9 10:14:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203622 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D9412C2BB58 for ; Mon, 9 Mar 2020 10:14:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BC90B2072A for ; Mon, 9 Mar 2020 10:14:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726635AbgCIKO4 (ORCPT ); Mon, 9 Mar 2020 06:14:56 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:48433 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726621AbgCIKOu (ORCPT ); Mon, 9 Mar 2020 06:14:50 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQj-0003mT-6Z; Mon, 09 Mar 2020 11:14:37 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQg-0001lq-NI; Mon, 09 Mar 2020 11:14:34 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org Subject: [PATCH v12 05/19] media: v4l2-fwnode: add v4l2_fwnode_connector Date: Mon, 9 Mar 2020 11:14:14 +0100 Message-Id: <20200309101428.15267-6-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Currently every driver needs to parse the connector endpoints by it self. This is the initial work to make this generic. A generic connector has common members and connector specific members. The common members are: - type - label (optional) - links - nr_of_links The specific members are stored within a union, since only one of them can be available at the time. Since this is the initial support the patch adds only the analog-connector specific ones. Signed-off-by: Marco Felsch --- [1] https://patchwork.kernel.org/cover/10794703/ v12: - convert links to a list - adapt docs - add connector name porperty v10: - drop unused V4L2_CONN_HDMI support v8: - rename CON -> CONN - supported_tvnorms_stds -> sdtv_stds and adapt description v7: - fix spelling issues - constify label - support variable label size - replace single remote_port/id members by links member of variable size - squash v4l2-connector into v4l2-fwnode @Jacopo: I dropped your r b tag because I changed the port/id logic. v6: - fix some spelling and style issues - rm unnecessary comments - drop vga and dvi connector - fix misspelt connector v2-v4: - nothing since the patch was squashed from series [1] into this series. include/media/v4l2-fwnode.h | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h index 7bba6dfa3fd6..6cf39d447b10 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h @@ -127,6 +127,63 @@ struct v4l2_fwnode_link { unsigned int remote_id; }; +/** + * enum v4l2_connector_type - connector type + * @V4L2_CONN_UNKNOWN: unknown connector type, no V4L2 connector configuration + * @V4L2_CONN_COMPOSITE: analog composite connector + * @V4L2_CONN_SVIDEO: analog svideo connector + */ +enum v4l2_connector_type { + V4L2_CONN_UNKNOWN, + V4L2_CONN_COMPOSITE, + V4L2_CONN_SVIDEO, +}; + +/** + * struct v4l2_connector_link - connector link data structure + * @head: structure to be used to add the link to the + * &struct v4l2_fwnode_connector + * @fwnode_link: &struct v4l2_fwnode_link link between the connector and the + * device the connector belongs to. + */ +struct v4l2_connector_link { + struct list_head head; + struct v4l2_fwnode_link fwnode_link; +}; + +/** + * struct v4l2_fwnode_connector_analog - analog connector data structure + * @sdtv_stds: sdtv standards this connector supports, set to V4L2_STD_ALL + * if no restrictions are specified. + */ +struct v4l2_fwnode_connector_analog { + v4l2_std_id sdtv_stds; +}; + +/** + * struct v4l2_fwnode_connector - the connector data structure + * @name: the connector device name + * @label: optional connector label + * @type: connector type + * @links: list of all connector &struct v4l2_connector_link links + * @nr_of_links: total number of links + * @connector: connector configuration + * @connector.analog: analog connector configuration + * &struct v4l2_fwnode_connector_analog + */ +struct v4l2_fwnode_connector { + const char *name; + const char *label; + enum v4l2_connector_type type; + struct list_head links; + unsigned int nr_of_links; + + union { + struct v4l2_fwnode_connector_analog analog; + /* future connectors */ + } connector; +}; + /** * v4l2_fwnode_endpoint_parse() - parse all fwnode node properties * @fwnode: pointer to the endpoint's fwnode handle From patchwork Mon Mar 9 10:14:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203625 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E6B9C2BB8C for ; Mon, 9 Mar 2020 10:14:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 19C8F20873 for ; Mon, 9 Mar 2020 10:14:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726647AbgCIKOv (ORCPT ); Mon, 9 Mar 2020 06:14:51 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:59227 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726622AbgCIKOu (ORCPT ); Mon, 9 Mar 2020 06:14:50 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQj-0003mW-6P; Mon, 09 Mar 2020 11:14:37 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQg-0001lt-Nr; Mon, 09 Mar 2020 11:14:34 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org Subject: [PATCH v12 06/19] media: v4l2-fwnode: add initial connector parsing support Date: Mon, 9 Mar 2020 11:14:15 +0100 Message-Id: <20200309101428.15267-7-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The patch adds the initial connector parsing code, so we can move from a driver specific parsing code to a generic one. Currently only the generic fields and the analog-connector specific fields are parsed. Parsing the other connector specific fields can be added by a simple callbacks. Signed-off-by: Marco Felsch --- [1] https://patchwork.kernel.org/cover/10794703/ v12: - all: adapt documentation - v4l2_fwnode_connector_parse_analog: convert to void - v4l2_fwnode_get_connector_type: new helper - split v4l2_fwnode_connector_alloc_parse into: - v4l2_fwnode_connector_parse: setup the connector ready to add links - v4l2_fwnode_connector_add_link: add a link to the connector - add helpers to get first and last link - v4l2_fwnode_connector_parse: improve error handling - v4l2_fwnode_connector_parse: improve connector type handling - v4l2_fwnode_connector_free: freed resources to NULL v10: - drop V4L2_CONN_HDMI support - adapt pr_err msg to reflect new state (-> connector is unkown) v9: - Fix leading semicolon found by kbuild semicolon.cocci v8: - V4L2_CON_* -> V4L2_CONN_* - tvnorms -> sdtv-standards - adapt to new v4l2_fwnode_connector_analog member - return error in case of V4L2_CONN_HDMI v7: @Jacopo: I dropped your r b tag becuase of the amount of changes I made.. - drop unnecessary comments - fix commet style - s/v4l2_fwnode_connector_conv.name/v4l2_fwnode_connector_conv.compatible/ - make label size variable and drop V4L2_CONNECTOR_MAX_LABEL usage - do not assign a default label in case of no label was specified - remove useless /* fall through */ comments - add support for N connector links - rename local variables to be more meaningful - adjust kernedoc - add v4l2_fwnode_connector_free() - improve error handling (use different error values) - make use of pr_warn_once() v6: - use unsigned count var - fix comment and style issues - place '/* fall through */' to correct places - fix error handling and cleanup by releasing fwnode - drop vga and dvi parsing support as those connectors are rarely used these days v5: - s/strlcpy/strscpy/ v2-v4: - nothing since the patch was squashed from series [1] into this series. --- drivers/media/v4l2-core/v4l2-fwnode.c | 164 ++++++++++++++++++++++++++ include/media/v4l2-fwnode.h | 82 +++++++++++++ 2 files changed, 246 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 78c32aebbe03..d8e1bcba2464 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -598,6 +598,170 @@ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link) } EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link); +static const struct v4l2_fwnode_connector_conv { + enum v4l2_connector_type type; + const char *compatible; +} connectors[] = { + { + .type = V4L2_CONN_COMPOSITE, + .compatible = "composite-video-connector", + }, { + .type = V4L2_CONN_SVIDEO, + .compatible = "svideo-connector", + }, +}; + +static enum v4l2_connector_type +v4l2_fwnode_string_to_connector_type(const char *con_str) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(connectors); i++) + if (!strcmp(con_str, connectors[i].compatible)) + return connectors[i].type; + + return V4L2_CONN_UNKNOWN; +} + +static void +v4l2_fwnode_connector_parse_analog(struct fwnode_handle *fwnode, + struct v4l2_fwnode_connector *vc) +{ + u32 stds; + int ret; + + ret = fwnode_property_read_u32(fwnode, "sdtv-standards", &stds); + + /* The property is optional. */ + vc->connector.analog.sdtv_stds = ret ? V4L2_STD_ALL : stds; +} + +void v4l2_fwnode_connector_free(struct v4l2_fwnode_connector *connector) +{ + struct v4l2_connector_link *link, *tmp; + + if (IS_ERR_OR_NULL(connector) || + connector->type == V4L2_CONN_UNKNOWN) + return; + + list_for_each_entry_safe(link, tmp, &connector->links, head) { + v4l2_fwnode_put_link(&link->fwnode_link); + list_del(&link->head); + kfree(link); + } + + kfree(connector->label); + connector->label = NULL; + connector = NULL; +} +EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_free); + +static enum v4l2_connector_type +v4l2_fwnode_get_connector_type(struct fwnode_handle *fwnode) +{ + const char *type_name; + int err; + + if (!fwnode) + return V4L2_CONN_UNKNOWN; + + /* The connector-type is stored within the compatible string. */ + err = fwnode_property_read_string(fwnode, "compatible", &type_name); + if (err) + return V4L2_CONN_UNKNOWN; + + return v4l2_fwnode_string_to_connector_type(type_name); +} + +int v4l2_fwnode_connector_parse(struct fwnode_handle *fwnode, + struct v4l2_fwnode_connector *connector) +{ + struct fwnode_handle *connector_node; + enum v4l2_connector_type connector_type; + const char *label; + int err; + + if (!fwnode) + return -EINVAL; + + memset(connector, 0, sizeof(*connector)); + + INIT_LIST_HEAD(&connector->links); + + connector_node = fwnode_graph_get_port_parent(fwnode); + connector_type = v4l2_fwnode_get_connector_type(connector_node); + if (connector_type == V4L2_CONN_UNKNOWN) { + fwnode_handle_put(connector_node); + connector_node = fwnode_graph_get_remote_port_parent(fwnode); + connector_type = v4l2_fwnode_get_connector_type(connector_node); + } + + if (connector_type == V4L2_CONN_UNKNOWN) { + pr_err("Unknown connector type\n"); + err = -ENOTCONN; + goto out; + } + + connector->type = connector_type; + connector->name = fwnode_get_name(connector_node); + err = fwnode_property_read_string(connector_node, "label", &label); + connector->label = err ? NULL : kstrdup_const(label, GFP_KERNEL); + + /* Parse the connector specific properties. */ + switch (connector->type) { + case V4L2_CONN_COMPOSITE: + case V4L2_CONN_SVIDEO: + v4l2_fwnode_connector_parse_analog(connector_node, connector); + break; + /* Avoid compiler warnings */ + case V4L2_CONN_UNKNOWN: + ; + } + +out: + fwnode_handle_put(connector_node); + + return err; +} +EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_parse); + +int v4l2_fwnode_connector_add_link(struct fwnode_handle *fwnode, + struct v4l2_fwnode_connector *connector) +{ + struct fwnode_handle *connector_ep; + struct v4l2_connector_link *link; + int err; + + if (!fwnode || !connector || connector->type == V4L2_CONN_UNKNOWN) + return -EINVAL; + + link = kzalloc(sizeof(*link), GFP_KERNEL); + if (!link) + return -ENOMEM; + + connector_ep = fwnode_graph_get_remote_endpoint(fwnode); + if (!connector_ep) + return -ENOTCONN; + + err = v4l2_fwnode_parse_link(connector_ep, &link->fwnode_link); + if (err) + goto err; + + fwnode_handle_put(connector_ep); + + list_add(&link->head, &connector->links); + connector->nr_of_links++; + + return 0; + +err: + kfree(link); + fwnode_handle_put(connector_ep); + + return err; +} +EXPORT_SYMBOL_GPL(v4l2_fwnode_connector_add_link); + static int v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev, struct v4l2_async_notifier *notifier, diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h index 6cf39d447b10..dd82d6d9764e 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h @@ -294,6 +294,66 @@ int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode, */ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link); +/** + * v4l2_fwnode_connector_free() - free the V4L2 connector acquired memory + * @connector: the V4L2 connector resources of which are to be released + * + * Free all allocated memory and put all links acquired by + * v4l2_fwnode_connector_parse() and v4l2_fwnode_connector_add_link(). + * + * It is safe to call this function with NULL argument or on a V4L2 connector + * the parsing of which failed. + */ +void v4l2_fwnode_connector_free(struct v4l2_fwnode_connector *connector); + +/** + * v4l2_fwnode_connector_parse() - initialize the 'struct v4l2_fwnode_connector' + * @fwnode: pointer to the subdev endpoint's fwnode handle where the connector + * is connected to or to the connector endpoint fwnode handle. + * @connector: pointer to the V4L2 fwnode connector data structure + * + * Fill the &struct v4l2_fwnode_connector with the connector type, label and + * all &enum v4l2_connector_type specific connector data. The label is optional + * so it is set to %NULL if no one was found. The function initialize the links + * to zero. Adding links to the connector is done by calling + * v4l2_fwnode_connector_add_link(). + * + * The memory allocated for the label must be freed when no longer needed. + * Freeing the memory is done by v4l2_fwnode_connector_free(). + * + * Return: + * * %0 on success or a negative error code on failure: + * * %-EINVAL if @fwnode is invalid + * * %-ENOTCONN if connector type is unknown or connector device can't be found + */ +int v4l2_fwnode_connector_parse(struct fwnode_handle *fwnode, + struct v4l2_fwnode_connector *connector); + +/** + * v4l2_fwnode_connector_add_link - add a link between a connector node and + * a v4l2-subdev node. + * @fwnode: pointer to the subdev endpoint's fwnode handle where the connector + * is connected to + * @connector: pointer to the V4L2 fwnode connector data structure + * + * Add a new &struct v4l2_connector_link link to the + * &struct v4l2_fwnode_connector connector links list. The link local_node + * points to the connector node, the remote_node to the host v4l2 (sub)dev. + * + * The taken references to remote_node and local_node must be dropped and the + * allocated memory must be freed when no longer needed. Both is done by calling + * v4l2_fwnode_connector_free(). + * + * Return: + * * %0 on success or a negative error code on failure: + * * %-EINVAL if @fwnode or @connector is invalid or @connector type is unknown + * * %-ENOMEM on link memory allocation failure + * * %-ENOTCONN if remote connector device can't be found + * * %-ENOLINK if link parsing between v4l2 (sub)dev and connector fails + */ +int v4l2_fwnode_connector_add_link(struct fwnode_handle *fwnode, + struct v4l2_fwnode_connector *connector); + /** * typedef parse_endpoint_func - Driver's callback function to be called on * each V4L2 fwnode endpoint. @@ -467,4 +527,26 @@ v4l2_async_register_fwnode_subdev(struct v4l2_subdev *sd, unsigned int num_ports, parse_endpoint_func parse_endpoint); +/* Helper macros to access the connector links. */ + +/** v4l2_connector_last_link - Helper macro to get the first + * &struct v4l2_fwnode_connector link + * @v4l2c: &struct v4l2_fwnode_connector owning the connector links + * + * This marco returns the first added &struct v4l2_connector_link connector + * link or @NULL if the connector has no links. + */ +#define v4l2_connector_first_link(v4l2c) \ + list_first_entry_or_null(&(v4l2c)->links, \ + struct v4l2_connector_link, head) + +/** v4l2_connector_last_link - Helper macro to get the last + * &struct v4l2_fwnode_connector link + * @v4l2c: &struct v4l2_fwnode_connector owning the connector links + * + * This marco returns the last &struct v4l2_connector_link added connector link. + */ +#define v4l2_connector_last_link(v4l2c) \ + list_last_entry(&(v4l2c)->links, struct v4l2_connector_link, head) + #endif /* _V4L2_FWNODE_H */ From patchwork Mon Mar 9 10:14:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203630 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EBEEAC3F2C6 for ; Mon, 9 Mar 2020 10:14:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C663324673 for ; Mon, 9 Mar 2020 10:14:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726475AbgCIKOp (ORCPT ); Mon, 9 Mar 2020 06:14:45 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:39287 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726467AbgCIKOp (ORCPT ); Mon, 9 Mar 2020 06:14:45 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQj-0003mY-Ds; Mon, 09 Mar 2020 11:14:37 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQg-0001lw-PH; Mon, 09 Mar 2020 11:14:34 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org, Javier Martinez Canillas , Mauro Carvalho Chehab , Rob Herring Subject: [PATCH v12 07/19] partial revert of "[media] tvp5150: add HW input connectors support" Date: Mon, 9 Mar 2020 11:14:16 +0100 Message-Id: <20200309101428.15267-8-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Javier Martinez Canillas Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support") added input signals support for the tvp5150, but the approach was found to be incorrect so the corresponding DT binding commit 82c2ffeb217a ("[media] tvp5150: document input connectors DT bindings") was reverted. This left the driver with an undocumented (and wrong) DT parsing logic, so lets get rid of this code as well until the input connectors support is implemented properly. It's a partial revert due other patches added on top of mentioned commit not allowing the commit to be reverted cleanly anymore. But all the code related to the DT parsing logic and input entities creation are removed. Suggested-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Acked-by: Laurent Pinchart [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define] Signed-off-by: Marco Felsch Signed-off-by: Mauro Carvalho Chehab Acked-by: Rob Herring --- drivers/media/i2c/tvp5150.c | 145 ---------------------------- include/dt-bindings/media/tvp5150.h | 2 - 2 files changed, 147 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index edad49cebcdf..11a5fd7e2f58 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -53,8 +53,6 @@ struct tvp5150 { struct v4l2_subdev sd; #ifdef CONFIG_MEDIA_CONTROLLER struct media_pad pads[TVP5150_NUM_PADS]; - struct media_entity input_ent[TVP5150_INPUT_NUM]; - struct media_pad input_pad[TVP5150_INPUT_NUM]; #endif struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -1169,40 +1167,6 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, return 0; } -/**************************************************************************** - Media entity ops - ****************************************************************************/ - -#ifdef CONFIG_MEDIA_CONTROLLER -static int tvp5150_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct tvp5150 *decoder = to_tvp5150(sd); - int i; - - for (i = 0; i < TVP5150_INPUT_NUM; i++) { - if (remote->entity == &decoder->input_ent[i]) - break; - } - - /* Do nothing for entities that are not input connectors */ - if (i == TVP5150_INPUT_NUM) - return 0; - - decoder->input = i; - - tvp5150_selmux(sd); - - return 0; -} - -static const struct media_entity_operations tvp5150_sd_media_ops = { - .link_setup = tvp5150_link_setup, -}; -#endif - /**************************************************************************** I2C Command ****************************************************************************/ @@ -1350,42 +1314,6 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } -static int tvp5150_registered(struct v4l2_subdev *sd) -{ -#ifdef CONFIG_MEDIA_CONTROLLER - struct tvp5150 *decoder = to_tvp5150(sd); - int ret = 0; - int i; - - for (i = 0; i < TVP5150_INPUT_NUM; i++) { - struct media_entity *input = &decoder->input_ent[i]; - struct media_pad *pad = &decoder->input_pad[i]; - - if (!input->name) - continue; - - decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; - - ret = media_entity_pads_init(input, 1, pad); - if (ret < 0) - return ret; - - ret = media_device_register_entity(sd->v4l2_dev->mdev, input); - if (ret < 0) - return ret; - - ret = media_create_pad_link(input, 0, &sd->entity, - TVP5150_PAD_IF_INPUT, 0); - if (ret < 0) { - media_device_unregister_entity(input); - return ret; - } - } -#endif - - return 0; -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = { @@ -1439,10 +1367,6 @@ static const struct v4l2_subdev_ops tvp5150_ops = { .pad = &tvp5150_pad_ops, }; -static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = { - .registered = tvp5150_registered, -}; - /**************************************************************************** I2C Client & Driver ****************************************************************************/ @@ -1595,12 +1519,6 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *ep; -#ifdef CONFIG_MEDIA_CONTROLLER - struct device_node *connectors, *child; - struct media_entity *input; - const char *name; - u32 input_type; -#endif unsigned int flags; int ret = 0; @@ -1624,67 +1542,6 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) decoder->mbus_type = bus_cfg.bus_type; -#ifdef CONFIG_MEDIA_CONTROLLER - connectors = of_get_child_by_name(np, "connectors"); - - if (!connectors) - goto err; - - for_each_available_child_of_node(connectors, child) { - ret = of_property_read_u32(child, "input", &input_type); - if (ret) { - dev_err(decoder->sd.dev, - "missing type property in node %pOFn\n", - child); - of_node_put(child); - goto err_connector; - } - - if (input_type >= TVP5150_INPUT_NUM) { - ret = -EINVAL; - of_node_put(child); - goto err_connector; - } - - input = &decoder->input_ent[input_type]; - - /* Each input connector can only be defined once */ - if (input->name) { - dev_err(decoder->sd.dev, - "input %s with same type already exists\n", - input->name); - of_node_put(child); - ret = -EINVAL; - goto err_connector; - } - - switch (input_type) { - case TVP5150_COMPOSITE0: - case TVP5150_COMPOSITE1: - input->function = MEDIA_ENT_F_CONN_COMPOSITE; - break; - case TVP5150_SVIDEO: - input->function = MEDIA_ENT_F_CONN_SVIDEO; - break; - } - - input->flags = MEDIA_ENT_FL_CONNECTOR; - - ret = of_property_read_string(child, "label", &name); - if (ret < 0) { - dev_err(decoder->sd.dev, - "missing label property in node %pOFn\n", - child); - of_node_put(child); - goto err_connector; - } - - input->name = name; - } - -err_connector: - of_node_put(connectors); -#endif err: of_node_put(ep); return ret; @@ -1735,7 +1592,6 @@ static int tvp5150_probe(struct i2c_client *c) } v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); - sd->internal_ops = &tvp5150_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; #if defined(CONFIG_MEDIA_CONTROLLER) @@ -1750,7 +1606,6 @@ static int tvp5150_probe(struct i2c_client *c) if (res < 0) return res; - sd->entity.ops = &tvp5150_sd_media_ops; #endif res = tvp5150_detect_version(core); diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h index 01eedf4985b8..dda00c038530 100644 --- a/include/dt-bindings/media/tvp5150.h +++ b/include/dt-bindings/media/tvp5150.h @@ -14,8 +14,6 @@ #define TVP5150_COMPOSITE1 1 #define TVP5150_SVIDEO 2 -#define TVP5150_INPUT_NUM 3 - /* TVP5150 HW outputs */ #define TVP5150_NORMAL 0 #define TVP5150_BLACK_SCREEN 1 From patchwork Mon Mar 9 10:14:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203628 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE48AC3F2C6 for ; Mon, 9 Mar 2020 10:14:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 81B1A20866 for ; Mon, 9 Mar 2020 10:14:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726610AbgCIKOs (ORCPT ); Mon, 9 Mar 2020 06:14:48 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:41659 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726549AbgCIKOs (ORCPT ); Mon, 9 Mar 2020 06:14:48 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQm-0003mb-Nw; Mon, 09 Mar 2020 11:14:40 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQg-0001lz-Pq; Mon, 09 Mar 2020 11:14:34 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org Subject: [PATCH v12 08/19] media: tvp5150: add input source selection of_graph support Date: Mon, 9 Mar 2020 11:14:17 +0100 Message-Id: <20200309101428.15267-9-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds the of_graph support to describe the tvp input connections. Physical the TVP5150 has three ports: AIP1A, AIP1B and YOUT. As result of discussion [1],[2] the device-tree maps these ports 1:1. Look at the Documentation for more information. Since the TVP5150 is a converter/bridge the device-tree must contain at least 1-input and 1-output port. The mc-connectors and mc-links are only created if the device-tree contains the corresponding connector nodes. If more than one connector is available the media_entity_operations.link_setup() callback ensures that only one connector is active. [1] https://www.spinics.net/lists/linux-media/msg138545.html [2] https://www.spinics.net/lists/linux-media/msg138546.html Signed-off-by: Marco Felsch --- Changelog: [1] https://patchwork.kernel.org/cover/10794703/ [2] https://patchwork.kernel.org/cover/10786553/ v12: - remove duplicated connector name assignment - make v4l2_fwnode_connector variable names unqiue - convert to new v4l2-fwnode helpers - drop tvp5150_add_connector() and use v4l2-fwnode helpers directly within tvp5150_parse_dt() - Add new tvp5150_validate_connectors() - add v4l2_fwnode_connector_free() and media_device_unregister_entity() to remove() to fix memory leak v11: - add local struct v4l2_fwnode_connector *v4lc to address 'over 80 characters' warning - fix casting style issue v8: - fix rebasing issue - fix error handling during tvp5150_registered() - adapt to new v4l2_connector_type enum v7: - don't init enum tvp5150_pads with TVP5150_COMPOSITE0 functionality - break some 80 character limitation to improve readability - fix comment style -> always start with capital letters and end with dot - fix some minor style issues - fix tvp5150_registered error handling - simplify tvp5150_mc_init - make connectors static -> since now only three connectors are possible (as described in DT) -> drop tvp5150.endpoints storage -> squash tvp5150_parse_dt and tvp5150_add_of_connectors - improve tvp5150_parse_dt: -> make parsing stricter and fix not detected missconfigured dt-data -> svideo must be connected now to port@[0,1]/endpoint@1 v6: - fix misspelled comments - use 'unsigned int' where it's possible - cleanup ifdef part-2: * tvp5150_mc_init, tvp5150_add_of_connectors: add surrounding CONFIG_MEDIA_CONTROLLER if def and stubs to improve quality - tvp5150_mc_init: uniform interface, use 'struct tvp5150' since all internal function do this. - tvp5150_add_of_connectors: call within probe() to make it cleaner - tvp5150_parse_dt: move local loop vars within the loop. v5: - Fixing build deps: - tvp5150_mc_init: fix CONFIG_MEDIA_CONTROLLER deps - struct tvp5150: drop CONFIG_MEDIA_CONTROLLER conditional property includes. This leads into to complex deps for futher development. - tvp5150_dt_cleanup: enable function only if CONFIG_OF is enabled - tvp5150_parse_dt: enable function only if CONFIG_OF is enabled - tvp5150_probe: call tvp5150_dt_cleanup only if CONFIG_OF is enabled - Simplify link_setup routine: - use generic connector parsing since both series [1,2] are squashed into one - struct tvp5150: drop pads_state and modify_second_link property due to link_setup() rework. - tvp5150_link_setup: add more comments - tvp5150_link_setup: simply the link setup routine a lot. Edit the 2nd link directly within the driver instead of a recursive media-framework call (__media_entity_setup_link). This improves the readability and shrinks the driver code. - tvp5150_link_setup: disable all active links in case user switches connectors without disable it first. - tvp5150_registered: simplify default link enable path due to link_setup() rework. - General cleanups - tvp5150_parse_dt: drop unecessary test - tvp5150_parse_dt: add err message due to misconfiguration - tvp5150_parse_dt: make use of V4L2_MBUS_UNKNOWN definition - s/dev_dbg/dev_dbg_lvl v4: - rebase on top of media_tree/master, fix merge conflict due to commit 60359a28d592 ("media: v4l: fwnode: Initialise the V4L2 fwnode endpoints to zero") v3: - probe(): s/err/err_free_v4l2_ctrls - drop MC dependency for tvp5150_pads v2: - adapt commit message - unify ifdef switches - rename tvp5150_valid_input -> tvp5150_of_valid_input, to be more precise - mc: use 2-input and 1-output pad - mc: link svideo connector to both input pads - mc: enable/disable svideo links in one go - mc: change link_setup() behaviour, switch the input src don't require a explicite disable before. - mc: rename 'local' media_pad param to tvp5150_pad to avoid confusion - mc: enable link to the first available connector and set the corresponding tvp5150 input src per default during registered() - mc/of: factor out oftree connector allocation - of: drop svideo dt port - of: move svideo connector to port@0/endpoint@1 - of: require at least 1-in and 1-out endpoint squash! media: tvp5150: add input source selection of_graph support v12: - fix remove path: delete possible media-entities --- drivers/media/i2c/tvp5150.c | 431 +++++++++++++++++++++++++++++++++--- 1 file changed, 404 insertions(+), 27 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 11a5fd7e2f58..90d4fd47f80d 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -32,6 +32,8 @@ #define TVP5150_FIELD V4L2_FIELD_ALTERNATE #define TVP5150_COLORSPACE V4L2_COLORSPACE_SMPTE170M +#define TVP5150_MAX_CONNECTORS 3 /* Check dt-bindings for more information */ + MODULE_DESCRIPTION("Texas Instruments TVP5150A/TVP5150AM1/TVP5151 video decoder driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_LICENSE("GPL v2"); @@ -44,16 +46,25 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg) enum tvp5150_pads { - TVP5150_PAD_IF_INPUT, + TVP5150_PAD_AIP1A, + TVP5150_PAD_AIP1B, TVP5150_PAD_VID_OUT, TVP5150_NUM_PADS }; +struct tvp5150_connector { + struct v4l2_fwnode_connector base; + struct media_entity ent; + struct media_pad pad; +}; + struct tvp5150 { struct v4l2_subdev sd; -#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pads[TVP5150_NUM_PADS]; -#endif + struct tvp5150_connector connectors[TVP5150_MAX_CONNECTORS]; + unsigned int connectors_num; + struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; struct regmap *regmap; @@ -1167,6 +1178,132 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, return 0; } +/**************************************************************************** + * Media entity ops + ****************************************************************************/ +#if defined(CONFIG_MEDIA_CONTROLLER) +static int tvp5150_set_link(struct media_pad *connector_pad, + struct media_pad *tvp5150_pad, u32 flags) +{ + struct media_link *link; + + link = media_entity_find_link(connector_pad, tvp5150_pad); + if (!link) + return -EINVAL; + + link->flags = flags; + link->reverse->flags = link->flags; + + return 0; +} + +static int tvp5150_disable_all_input_links(struct tvp5150 *decoder) +{ + struct media_pad *connector_pad; + unsigned int i; + int err; + + for (i = 0; i < TVP5150_NUM_PADS - 1; i++) { + connector_pad = media_entity_remote_pad(&decoder->pads[i]); + if (!connector_pad) + continue; + + err = tvp5150_set_link(connector_pad, &decoder->pads[i], 0); + if (err) + return err; + } + + return 0; +} + +static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, + u32 config); + +static int tvp5150_link_setup(struct media_entity *entity, + const struct media_pad *tvp5150_pad, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct tvp5150 *decoder = to_tvp5150(sd); + struct media_pad *other_tvp5150_pad = + &decoder->pads[tvp5150_pad->index ^ 1]; + struct v4l2_fwnode_connector *v4l2c; + bool is_svideo = false; + unsigned int i; + int err; + + /* + * The TVP5150 state is determined by the enabled sink pad link(s). + * Enabling or disabling the source pad link has no effect. + */ + if (tvp5150_pad->flags & MEDIA_PAD_FL_SOURCE) + return 0; + + /* Check if the svideo connector should be enabled */ + for (i = 0; i < decoder->connectors_num; i++) { + if (remote->entity == &decoder->connectors[i].ent) { + v4l2c = &decoder->connectors[i].base; + is_svideo = v4l2c->type == V4L2_CONN_SVIDEO; + break; + } + } + + dev_dbg_lvl(sd->dev, 1, debug, "link setup '%s':%d->'%s':%d[%d]", + remote->entity->name, remote->index, + tvp5150_pad->entity->name, tvp5150_pad->index, + flags & MEDIA_LNK_FL_ENABLED); + if (is_svideo) + dev_dbg_lvl(sd->dev, 1, debug, + "link setup '%s':%d->'%s':%d[%d]", + remote->entity->name, remote->index, + other_tvp5150_pad->entity->name, + other_tvp5150_pad->index, + flags & MEDIA_LNK_FL_ENABLED); + + /* + * The TVP5150 has an internal mux which allows the following setup: + * + * comp-connector1 --\ + * |---> AIP1A + * / + * svideo-connector -| + * \ + * |---> AIP1B + * comp-connector2 --/ + * + * We can't rely on user space that the current connector gets disabled + * first before enabling the new connector. Disable all active + * connector links to be on the safe side. + */ + err = tvp5150_disable_all_input_links(decoder); + if (err) + return err; + + tvp5150_s_routing(sd, is_svideo ? TVP5150_SVIDEO : tvp5150_pad->index, + flags & MEDIA_LNK_FL_ENABLED ? TVP5150_NORMAL : + TVP5150_BLACK_SCREEN, 0); + + if (flags & MEDIA_LNK_FL_ENABLED) { + /* + * S-Video connector is conneted to both ports AIP1A and AIP1B. + * Both links must be enabled in one-shot regardless which link + * the user requests. + */ + if (is_svideo) { + err = tvp5150_set_link((struct media_pad *)remote, + other_tvp5150_pad, flags); + if (err) + return err; + } + } + + return 0; +} + +static const struct media_entity_operations tvp5150_sd_media_ops = { + .link_setup = tvp5150_link_setup, +}; +#endif /**************************************************************************** I2C Command ****************************************************************************/ @@ -1314,6 +1451,76 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } +static int tvp5150_registered(struct v4l2_subdev *sd) +{ +#if defined(CONFIG_MEDIA_CONTROLLER) + struct tvp5150 *decoder = to_tvp5150(sd); + unsigned int i; + int ret; + + /* + * Setup connector pads and links. Enable the link to the first + * available connector per default. + */ + for (i = 0; i < decoder->connectors_num; i++) { + struct media_entity *con = &decoder->connectors[i].ent; + struct media_pad *pad = &decoder->connectors[i].pad; + struct v4l2_fwnode_connector *v4l2c = + &decoder->connectors[i].base; + struct v4l2_connector_link *link = + v4l2_connector_first_link(v4l2c); + unsigned int port = link->fwnode_link.remote_port; + unsigned int flags = i ? 0 : MEDIA_LNK_FL_ENABLED; + bool is_svideo = v4l2c->type == V4L2_CONN_SVIDEO; + + pad->flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(con, 1, pad); + if (ret < 0) + goto err; + + ret = media_device_register_entity(sd->v4l2_dev->mdev, con); + if (ret < 0) + goto err; + + ret = media_create_pad_link(con, 0, &sd->entity, port, flags); + if (ret < 0) + goto err; + + if (is_svideo) { + /* + * Check tvp5150_link_setup() comments for more + * information. + */ + link = v4l2_connector_last_link(v4l2c); + port = link->fwnode_link.remote_port; + ret = media_create_pad_link(con, 0, &sd->entity, port, + flags); + if (ret < 0) + goto err; + } + + /* Enable default input. */ + if (flags == MEDIA_LNK_FL_ENABLED) { + decoder->input = + is_svideo ? TVP5150_SVIDEO : + port == 0 ? TVP5150_COMPOSITE0 : + TVP5150_COMPOSITE1; + + tvp5150_selmux(sd); + } + } + + return 0; + +err: + for (i = 0; i < decoder->connectors_num; i++) + media_device_unregister_entity(&decoder->connectors[i].ent); + return ret; +#endif + + return 0; +} + /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = { @@ -1367,6 +1574,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = { .pad = &tvp5150_pad_ops, }; +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = { + .registered = tvp5150_registered, +}; + /**************************************************************************** I2C Client & Driver ****************************************************************************/ @@ -1515,35 +1726,205 @@ static int tvp5150_init(struct i2c_client *c) return 0; } +#if defined(CONFIG_MEDIA_CONTROLLER) +static int tvp5150_mc_init(struct tvp5150 *decoder) +{ + struct v4l2_subdev *sd = &decoder->sd; + unsigned int i; + + sd->entity.ops = &tvp5150_sd_media_ops; + sd->entity.function = MEDIA_ENT_F_ATV_DECODER; + + for (i = 0; i < TVP5150_NUM_PADS - 1; i++) { + decoder->pads[i].flags = MEDIA_PAD_FL_SINK; + decoder->pads[i].sig_type = PAD_SIGNAL_ANALOG; + } + + decoder->pads[i].flags = MEDIA_PAD_FL_SOURCE; + decoder->pads[i].sig_type = PAD_SIGNAL_DV; + + return media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, + decoder->pads); +} + +#else /* !defined(CONFIG_MEDIA_CONTROLLER) */ + +static inline int tvp5150_mc_init(struct tvp5150 *decoder) +{ + return 0; +} +#endif /* defined(CONFIG_MEDIA_CONTROLLER) */ + +static int tvp5150_validate_connectors(struct tvp5150 *decoder) +{ + struct device *dev = decoder->sd.dev; + struct tvp5150_connector *tvpc; + struct v4l2_fwnode_connector *v4l2c; + unsigned int i; + + if (!decoder->connectors_num) { + dev_err(dev, "No valid connector found\n"); + return -ENODEV; + } + + for (i = 0; i < decoder->connectors_num; i++) { + struct v4l2_connector_link *link0 = NULL; + struct v4l2_connector_link *link1; + + tvpc = &decoder->connectors[i]; + v4l2c = &tvpc->base; + + if (v4l2c->type == V4L2_CONN_COMPOSITE) { + if (v4l2c->nr_of_links != 1) { + dev_err(dev, "Composite: connector needs 1 link\n"); + return -EINVAL; + } + link0 = v4l2_connector_first_link(v4l2c); + if (!link0) { + dev_err(dev, "Composite: invalid first link\n"); + return -EINVAL; + } + if (link0->fwnode_link.remote_id == 1) { + dev_err(dev, "Composite: invalid endpoint id\n"); + return -EINVAL; + } + } + + if (v4l2c->type == V4L2_CONN_SVIDEO) { + if (v4l2c->nr_of_links != 2) { + dev_err(dev, "SVideo: connector needs 2 links\n"); + return -EINVAL; + } + link0 = v4l2_connector_first_link(v4l2c); + if (!link0) { + dev_err(dev, "SVideo: invalid first link\n"); + return -EINVAL; + } + link1 = v4l2_connector_last_link(v4l2c); + if (link0->fwnode_link.remote_port == + link1->fwnode_link.remote_port) { + dev_err(dev, "SVideo: invalid link setup\n"); + return -EINVAL; + } + } + } + + return 0; +} + static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) { - struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; - struct device_node *ep; - unsigned int flags; - int ret = 0; + struct device *dev = decoder->sd.dev; + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_UNKNOWN + }; + struct device_node *ep_np; + struct tvp5150_connector *tvpc; + struct v4l2_fwnode_connector *v4l2c; + unsigned int flags, ep_num; + unsigned int i; + int ret; - ep = of_graph_get_next_endpoint(np, NULL); - if (!ep) + /* At least 1 output and 1 input */ + ep_num = of_graph_get_endpoint_count(np); + if (ep_num < 2 || ep_num > 5) { + dev_err(dev, "At least 1 input and 1 output must be connected to the device.\n"); return -EINVAL; + } - ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg); + /* Layout if all connectors are used: + * + * tvp-5150 port@0 (AIP1A) + * endpoint@0 -----------> Comp0-Con port + * endpoint@1 --------+--> Svideo-Con port + * tvp-5150 port@1 (AIP1B) | + * endpoint@1 --------+ + * endpoint@0 -----------> Comp1-Con port + * tvp-5150 port@2 + * endpoint (video bitstream output at YOUT[0-7] parallel bus) + */ + for_each_endpoint_of_node(np, ep_np) { + struct fwnode_handle *ep_fwnode = of_fwnode_handle(ep_np); + unsigned int next_connector = decoder->connectors_num; + struct of_endpoint ep; + + of_graph_parse_endpoint(ep_np, &ep); + if (ep.port > 1 || ep.id > 1) { + dev_dbg(dev, "Ignore connector on port@%u/ep@%u\n", + ep.port, ep.id); + continue; + } + + tvpc = &decoder->connectors[next_connector]; + v4l2c = &tvpc->base; + + if (ep.port == 0 || (ep.port == 1 && ep.id == 0)) { + ret = v4l2_fwnode_connector_parse(ep_fwnode, v4l2c); + if (ret) + goto err_put; + ret = v4l2_fwnode_connector_add_link(ep_fwnode, v4l2c); + if (ret) + goto err_put; + decoder->connectors_num++; + } else { + /* Adding the 2nd svideo link */ + for (i = 0; i < TVP5150_MAX_CONNECTORS; i++) { + tvpc = &decoder->connectors[i]; + v4l2c = &tvpc->base; + if (v4l2c->type == V4L2_CONN_SVIDEO) + break; + } + + ret = v4l2_fwnode_connector_add_link(ep_fwnode, v4l2c); + if (ret) + goto err_put; + } + } + + ret = tvp5150_validate_connectors(decoder); if (ret) - goto err; + goto err_free; + + for (i = 0; i < decoder->connectors_num; i++) { + tvpc = &decoder->connectors[i]; + v4l2c = &tvpc->base; + tvpc->ent.flags = MEDIA_ENT_FL_CONNECTOR; + tvpc->ent.function = v4l2c->type == V4L2_CONN_SVIDEO ? + MEDIA_ENT_F_CONN_SVIDEO : MEDIA_ENT_F_CONN_COMPOSITE; + tvpc->ent.name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", + v4l2c->name, v4l2c->label ? + v4l2c->label : ""); + } - flags = bus_cfg.bus.parallel.flags; + ep_np = of_graph_get_endpoint_by_regs(np, TVP5150_PAD_VID_OUT, 0); + if (!ep_np) { + dev_err(dev, "Error no output endpoint available\n"); + goto err_free; + } + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np), &bus_cfg); + of_node_put(ep_np); + if (ret) + goto err_free; + flags = bus_cfg.bus.parallel.flags; if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL && !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH && flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH && flags & V4L2_MBUS_FIELD_EVEN_LOW)) { ret = -EINVAL; - goto err; + goto err_free; } decoder->mbus_type = bus_cfg.bus_type; -err: - of_node_put(ep); + return 0; + +err_put: + of_node_put(ep_np); +err_free: + for (i = 0; i < TVP5150_MAX_CONNECTORS; i++) + v4l2_fwnode_connector_free(&decoder->connectors[i].base); + return ret; } @@ -1592,22 +1973,13 @@ static int tvp5150_probe(struct i2c_client *c) } v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); + sd->internal_ops = &tvp5150_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; -#if defined(CONFIG_MEDIA_CONTROLLER) - core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; - core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG; - core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; - core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV; - - sd->entity.function = MEDIA_ENT_F_ATV_DECODER; - - res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads); - if (res < 0) + res = tvp5150_mc_init(core); + if (res) return res; -#endif - res = tvp5150_detect_version(core); if (res < 0) return res; @@ -1668,11 +2040,16 @@ static int tvp5150_remove(struct i2c_client *c) { struct v4l2_subdev *sd = i2c_get_clientdata(c); struct tvp5150 *decoder = to_tvp5150(sd); + unsigned int i; dev_dbg_lvl(sd->dev, 1, debug, "tvp5150.c: removing tvp5150 adapter on address 0x%x\n", c->addr << 1); + for (i = 0; i < decoder->connectors_num; i++) + v4l2_fwnode_connector_free(&decoder->connectors[i].base); + for (i = 0; i < decoder->connectors_num; i++) + media_device_unregister_entity(&decoder->connectors[i].ent); v4l2_async_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); return 0; From patchwork Mon Mar 9 10:14:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203621 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40626C10F27 for ; Mon, 9 Mar 2020 10:16:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1FDB32072A for ; Mon, 9 Mar 2020 10:16:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726217AbgCIKQU (ORCPT ); Mon, 9 Mar 2020 06:16:20 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:44099 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726539AbgCIKOq (ORCPT ); Mon, 9 Mar 2020 06:14:46 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQj-0003ml-6N; Mon, 09 Mar 2020 11:14:37 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQg-0001mE-Ts; Mon, 09 Mar 2020 11:14:34 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org Subject: [PATCH v12 13/19] media: tvp5150: move irq en-/disable into runtime-pm ops Date: Mon, 9 Mar 2020 11:14:22 +0100 Message-Id: <20200309101428.15267-14-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org As documented in [1] the runtime-pm ops are used to set the device into a fully 'workable' state. Therefore it can be used to enable or disable the irqs. [1] https://www.kernel.org/doc/html/latest/power/runtime_pm.html Signed-off-by: Marco Felsch --- v12: - change commit header and message -> former "media: tvp5150: add s_power callback" - drop s_power() callback and use pm_runtime callbacks instead drivers/media/i2c/tvp5150.c | 61 +++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 1da0ff1ffc55..313d2a43d79e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1356,16 +1357,51 @@ static const struct media_entity_operations tvp5150_sd_media_ops = { /**************************************************************************** I2C Command ****************************************************************************/ +static int __maybe_unused tvp5150_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct tvp5150 *decoder = to_tvp5150(sd); + + if (decoder->irq) + /* Disable lock interrupt */ + return regmap_update_bits(decoder->regmap, + TVP5150_INT_ENABLE_REG_A, + TVP5150_INT_A_LOCK, 0); + return 0; +} + +static int __maybe_unused tvp5150_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct tvp5150 *decoder = to_tvp5150(sd); + + if (decoder->irq) + /* Enable lock interrupt */ + return regmap_update_bits(decoder->regmap, + TVP5150_INT_ENABLE_REG_A, + TVP5150_INT_A_LOCK, + TVP5150_INT_A_LOCK); + return 0; +} static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { struct tvp5150 *decoder = to_tvp5150(sd); - unsigned int mask, val = 0, int_val = 0; + unsigned int mask, val = 0; + int ret; mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE | TVP5150_MISC_CTL_CLOCK_OE; if (enable) { + ret = pm_runtime_get_sync(sd->dev); + if (ret < 0) { + pm_runtime_put_noidle(sd->dev); + return ret; + } + tvp5150_enable(sd); /* Enable outputs if decoder is locked */ @@ -1373,15 +1409,13 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) val = decoder->lock ? decoder->oe : 0; else val = decoder->oe; - int_val = TVP5150_INT_A_LOCK; + v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt); + } else { + pm_runtime_put(sd->dev); } regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val); - if (decoder->irq) - /* Enable / Disable lock interrupt */ - regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A, - TVP5150_INT_A_LOCK, int_val); return 0; } @@ -2077,6 +2111,11 @@ static int tvp5150_probe(struct i2c_client *c) if (debug > 1) tvp5150_log_status(sd); + + pm_runtime_set_active(&c->dev); + pm_runtime_enable(&c->dev); + pm_runtime_idle(&c->dev); + return 0; err: @@ -2100,11 +2139,20 @@ static int tvp5150_remove(struct i2c_client *c) media_device_unregister_entity(&decoder->connectors[i].ent); v4l2_async_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); + pm_runtime_disable(&c->dev); + pm_runtime_set_suspended(&c->dev); + return 0; } /* ----------------------------------------------------------------------- */ +static const struct dev_pm_ops tvp5150_pm_ops = { + SET_RUNTIME_PM_OPS(tvp5150_runtime_suspend, + tvp5150_runtime_resume, + NULL) +}; + static const struct i2c_device_id tvp5150_id[] = { { "tvp5150", 0 }, { } @@ -2123,6 +2171,7 @@ static struct i2c_driver tvp5150_driver = { .driver = { .of_match_table = of_match_ptr(tvp5150_of_match), .name = "tvp5150", + .pm = &tvp5150_pm_ops, }, .probe_new = tvp5150_probe, .remove = tvp5150_remove, From patchwork Mon Mar 9 10:14:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203623 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 039E5C33C88 for ; Mon, 9 Mar 2020 10:15:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D0C3020848 for ; Mon, 9 Mar 2020 10:15:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726682AbgCIKPC (ORCPT ); Mon, 9 Mar 2020 06:15:02 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:41075 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725796AbgCIKOr (ORCPT ); Mon, 9 Mar 2020 06:14:47 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQm-0003mq-RD; Mon, 09 Mar 2020 11:14:40 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQg-0001mK-Vk; Mon, 09 Mar 2020 11:14:34 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org Subject: [PATCH v12 15/19] media: tvp5150: add subdev open/close callbacks Date: Mon, 9 Mar 2020 11:14:24 +0100 Message-Id: <20200309101428.15267-16-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Bring the device into a working state upon a open/close call. Currently this involves only the interrupt enable/disable process but can be extended in the future. Signed-off-by: Marco Felsch --- v12: - new patch drivers/media/i2c/tvp5150.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 9bad3192358d..abc784dbeb81 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1618,6 +1618,26 @@ static int tvp5150_registered(struct v4l2_subdev *sd) return 0; } +static int tvp5150_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + int ret; + + ret = pm_runtime_get_sync(sd->dev); + if (ret < 0) { + pm_runtime_put_noidle(sd->dev); + return ret; + } + + return 0; +} + +static int tvp5150_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + pm_runtime_put(sd->dev); + + return 0; +} + /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = { @@ -1675,6 +1695,8 @@ static const struct v4l2_subdev_ops tvp5150_ops = { static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = { .registered = tvp5150_registered, + .open = tvp5150_open, + .close = tvp5150_close, }; /**************************************************************************** From patchwork Mon Mar 9 10:14:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 203627 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0FDDC18E5B for ; Mon, 9 Mar 2020 10:14:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id ABE0C20866 for ; Mon, 9 Mar 2020 10:14:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726622AbgCIKOv (ORCPT ); Mon, 9 Mar 2020 06:14:51 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:47531 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726620AbgCIKOu (ORCPT ); Mon, 9 Mar 2020 06:14:50 -0400 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28] helo=dude02.lab.pengutronix.de) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jBFQj-0003mx-6N; Mon, 09 Mar 2020 11:14:37 +0100 Received: from mfe by dude02.lab.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1jBFQh-0001mU-2W; Mon, 09 Mar 2020 11:14:35 +0100 From: Marco Felsch To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, jacopo+renesas@jmondi.org, robh+dt@kernel.org, laurent.pinchart@ideasonboard.com Cc: devicetree@vger.kernel.org, kernel@pengutronix.de, linux-media@vger.kernel.org Subject: [PATCH v12 18/19] media: tvp5150: add support to limit sdtv standards Date: Mon, 9 Mar 2020 11:14:27 +0100 Message-Id: <20200309101428.15267-19-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101428.15267-1-m.felsch@pengutronix.de> References: <20200309101428.15267-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: devicetree@vger.kernel.org Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The tvp5150 accepts NTSC(M,J,4.43), PAL (B,D,G,H,I,M,N) and SECAM video data and is able to auto-detect the input signal. The auto-detection does not work if the connector does not receive an input signal and the tvp5150 might not be configured correctly. This misconfiguration leads into wrong decoded video streams if the tvp5150 gets powered on before the video signal is present. Limit the supported sdtv standards according to the actual selected connector to avoid a misconfiguration. Signed-off-by: Marco Felsch --- [1] https://patchwork.kernel.org/cover/10794703/ v12: - use unique v4l2c naming - move tv-norm check to new tvp5150_validate_connectors() v11: - address 80 character warnings by: - use struct v4l2_fwnode_connector *v4lc - add truct v4l2_fwnode_connector_analog *v4lca v8: - adapt commit message - fix rebasing issue - apdapt to new v4l2_fwnode_connector_analog naming - fix cur_connector update during tvp5150_link_setup() -> Only update if we have of-connectors. - fix supported_stds detection during tvp5150_s_std() -> use connectors_num to detect of-connectors presence v5: - probe() initialize supported tv-norms according the given connectors if they are available. - check if media-controller is used. Don't limit the norm if it isn't used. - add more logic to be smarter during connector changing so it is intuitiver for the user space. v2-v4: - nothing since the patch was squashed from series [1] into this series. --- drivers/media/i2c/tvp5150.c | 76 ++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index abc784dbeb81..fb24581e86c1 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -34,6 +34,13 @@ #define TVP5150_MBUS_FMT MEDIA_BUS_FMT_UYVY8_2X8 #define TVP5150_FIELD V4L2_FIELD_ALTERNATE #define TVP5150_COLORSPACE V4L2_COLORSPACE_SMPTE170M +#define TVP5150_STD_MASK (V4L2_STD_NTSC | \ + V4L2_STD_NTSC_443 | \ + V4L2_STD_PAL | \ + V4L2_STD_PAL_M | \ + V4L2_STD_PAL_N | \ + V4L2_STD_PAL_Nc | \ + V4L2_STD_SECAM) #define TVP5150_MAX_CONNECTORS 3 /* Check dt-bindings for more information */ @@ -66,6 +73,7 @@ struct tvp5150 { struct media_pad pads[TVP5150_NUM_PADS]; struct tvp5150_connector connectors[TVP5150_MAX_CONNECTORS]; + struct tvp5150_connector *cur_connector; unsigned int connectors_num; struct v4l2_ctrl_handler hdl; @@ -785,17 +793,33 @@ static int tvp5150_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std) { struct tvp5150 *decoder = to_tvp5150(sd); + struct tvp5150_connector *cur_con = decoder->cur_connector; + v4l2_std_id supported_stds; if (decoder->norm == std) return 0; + /* In case of no of-connectors are available no limitations are made */ + if (!decoder->connectors_num) + supported_stds = V4L2_STD_ALL; + else + supported_stds = cur_con->base.connector.analog.sdtv_stds; + + /* + * Check if requested std or group of std's is/are supported by the + * connector. + */ + if ((supported_stds & std) == 0) + return -EINVAL; + /* Change cropping height limits */ if (std & V4L2_STD_525_60) decoder->rect.height = TVP5150_V_MAX_525_60; else decoder->rect.height = TVP5150_V_MAX_OTHERS; - decoder->norm = std; + /* Set only the specific supported std in case of group of std's. */ + decoder->norm = supported_stds & std; return tvp5150_set_std(sd, std); } @@ -1335,6 +1359,9 @@ static int tvp5150_link_setup(struct media_entity *entity, TVP5150_BLACK_SCREEN, 0); if (flags & MEDIA_LNK_FL_ENABLED) { + struct v4l2_fwnode_connector_analog *v4l2ca; + u32 new_norm; + /* * S-Video connector is conneted to both ports AIP1A and AIP1B. * Both links must be enabled in one-shot regardless which link @@ -1346,6 +1373,28 @@ static int tvp5150_link_setup(struct media_entity *entity, if (err) return err; } + + if (!decoder->connectors_num) + return 0; + + /* Update the current connector */ + decoder->cur_connector = + container_of(remote, struct tvp5150_connector, pad); + + /* + * Do nothing if the new connector supports the same tv-norms as + * the old one. + */ + v4l2ca = &decoder->cur_connector->base.connector.analog; + new_norm = decoder->norm & v4l2ca->sdtv_stds; + if (decoder->norm == new_norm) + return 0; + + /* + * Fallback to the new connector tv-norms if we can't find any + * common between the current tv-norm and the new one. + */ + tvp5150_s_std(sd, new_norm ? new_norm : v4l2ca->sdtv_stds); } return 0; @@ -1604,6 +1653,8 @@ static int tvp5150_registered(struct v4l2_subdev *sd) TVP5150_COMPOSITE1; tvp5150_selmux(sd); + decoder->cur_connector = &decoder->connectors[i]; + tvp5150_s_std(sd, v4l2c->connector.analog.sdtv_stds); } } @@ -1928,6 +1979,12 @@ static int tvp5150_validate_connectors(struct tvp5150 *decoder) return -EINVAL; } } + + if (!(v4l2c->connector.analog.sdtv_stds & TVP5150_STD_MASK)) { + dev_err(dev, "Unsupported tv-norm on connector %s\n", + v4l2c->name); + return -EINVAL; + } } return 0; @@ -2060,6 +2117,7 @@ static int tvp5150_probe(struct i2c_client *c) struct v4l2_subdev *sd; struct device_node *np = c->dev.of_node; struct regmap *map; + unsigned int i; int res; /* Check if the adapter supports the needed features */ @@ -2104,7 +2162,21 @@ static int tvp5150_probe(struct i2c_client *c) if (res < 0) return res; - core->norm = V4L2_STD_ALL; /* Default is autodetect */ + /* + * Iterate over all available connectors in case they are supported and + * successfully parsed. Fallback to default autodetect in case they + * aren't supported. + */ + for (i = 0; i < core->connectors_num; i++) { + struct v4l2_fwnode_connector *v4l2c; + + v4l2c = &core->connectors[i].base; + core->norm |= v4l2c->connector.analog.sdtv_stds; + } + + if (!core->connectors_num) + core->norm = V4L2_STD_ALL; + core->detected_norm = V4L2_STD_UNKNOWN; core->input = TVP5150_COMPOSITE1; core->enable = true;