From patchwork Mon Aug 26 15:26:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 11114881 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 22F461395 for ; Mon, 26 Aug 2019 15:27:16 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0B932217F5 for ; Mon, 26 Aug 2019 15:27:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0B932217F5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A4CAA6E229; Mon, 26 Aug 2019 15:27:12 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by gabe.freedesktop.org (Postfix) with ESMTPS id B5E836E231 for ; Mon, 26 Aug 2019 15:27:08 +0000 (UTC) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:2c:6930:5cf4:84a1:2763:fe0d]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: bbrezillon) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 85FAA28BD67; Mon, 26 Aug 2019 16:27:06 +0100 (BST) From: Boris Brezillon To: dri-devel@lists.freedesktop.org Subject: [PATCH v2 18/21] drm/bridge: lvds-encoder: Implement basic bus format negotiation Date: Mon, 26 Aug 2019 17:26:46 +0200 Message-Id: <20190826152649.13820-19-boris.brezillon@collabora.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190826152649.13820-1-boris.brezillon@collabora.com> References: <20190826152649.13820-1-boris.brezillon@collabora.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Nikita Yushchenko , Jernej Skrabec , Laurent Pinchart , Neil Armstrong , Andrey Smirnov , Jonas Karlman , Seung-Woo Kim , Kyungmin Park , Thierry Reding , Chris Healy , Boris Brezillon , kernel@collabora.com, Sam Ravnborg Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Some LVDS encoder might support several input/output bus formats. Add a way to describe the one used on a specific design by adding optional 'data-mapping' properties to the input/output ports. Signed-off-by: Boris Brezillon --- Changes in v2: * Make the bus-format negotiation logic more generic --- .../display/bridge/lvds-transmitter.txt | 12 ++ drivers/gpu/drm/bridge/lvds-encoder.c | 105 ++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt index 60091db5dfa5..db51eab216f7 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt @@ -36,6 +36,18 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt. - Video port 0 for parallel input - Video port 1 for LVDS output +Optional port 0 node properties: + +- data-mapping: can be one of the following values + "rgb-24" + "rgb-18" + +Optional port 0 node properties: + +- data-mapping: can be one of the following values + "jeida-18" + "jeida-24" + "vesa-24" Example ------- diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c index 2ab2c234f26c..38cad7a7d828 100644 --- a/drivers/gpu/drm/bridge/lvds-encoder.c +++ b/drivers/gpu/drm/bridge/lvds-encoder.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,8 @@ struct lvds_encoder { struct drm_bridge bridge; struct drm_bridge *panel_bridge; struct gpio_desc *powerdown_gpio; + u32 output_fmt; + u32 input_fmt; }; static int lvds_encoder_attach(struct drm_bridge *bridge) @@ -48,12 +51,86 @@ static void lvds_encoder_disable(struct drm_bridge *bridge) gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1); } +static void lvds_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts, + u32 *input_fmts) +{ + struct lvds_encoder *lvds_encoder = container_of(bridge, + struct lvds_encoder, + bridge); + + if (output_fmt == MEDIA_BUS_FMT_FIXED || + output_fmt == lvds_encoder->output_fmt) + *num_input_fmts = 1; + else + *num_input_fmts = 0; + + if (*num_input_fmts && input_fmts) + input_fmts[0] = lvds_encoder->input_fmt; +} + +static int lvds_encoder_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + /* Propagate the bus_flags. */ + bridge_state->input_bus_cfg.flags = bridge_state->output_bus_cfg.flags; + return 0; +} + static struct drm_bridge_funcs funcs = { .attach = lvds_encoder_attach, .enable = lvds_encoder_enable, .disable = lvds_encoder_disable, + .atomic_get_input_bus_fmts = lvds_atomic_get_input_bus_fmts, + .atomic_check = lvds_encoder_atomic_check, }; +struct of_data_mapping { + const char *name; + u32 id; +}; + +static const struct of_data_mapping output_data_mappings[] = { + { "jeida-18", MEDIA_BUS_FMT_RGB666_1X7X3_SPWG }, + { "jeida-24", MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA }, + { "vesa-24", MEDIA_BUS_FMT_RGB888_1X7X4_SPWG }, +}; + +static const struct of_data_mapping input_data_mappings[] = { + { "rgb-24", MEDIA_BUS_FMT_RGB888_1X24 }, + { "rgb-18", MEDIA_BUS_FMT_RGB666_1X18 }, +}; + +static int of_get_data_mapping(struct device_node *port, + const struct of_data_mapping *mappings, + unsigned int num_mappings, + u32 *fmt) +{ + const char *name = NULL; + unsigned int i; + + of_property_read_string(port, "data-mapping", &name); + if (!name) { + *fmt = MEDIA_BUS_FMT_FIXED; + return 0; + } + + for (i = 0; i < num_mappings; i++) { + if (!strcmp(mappings[i].name, name)) { + *fmt = mappings[i].id; + return 0; + } + } + + return -ENOTSUPP; +} + static int lvds_encoder_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -62,11 +139,15 @@ static int lvds_encoder_probe(struct platform_device *pdev) struct device_node *panel_node; struct drm_panel *panel; struct lvds_encoder *lvds_encoder; + int ret; lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), GFP_KERNEL); if (!lvds_encoder) return -ENOMEM; + lvds_encoder->input_fmt = MEDIA_BUS_FMT_FIXED; + lvds_encoder->output_fmt = MEDIA_BUS_FMT_FIXED; + lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); if (IS_ERR(lvds_encoder->powerdown_gpio)) { @@ -77,6 +158,21 @@ static int lvds_encoder_probe(struct platform_device *pdev) return err; } + port = of_graph_get_port_by_id(dev->of_node, 0); + if (!port) { + dev_dbg(dev, "port 0 not found\n"); + return -ENXIO; + } + + ret = of_get_data_mapping(port, input_data_mappings, + ARRAY_SIZE(input_data_mappings), + &lvds_encoder->input_fmt); + of_node_put(port); + if (ret) { + dev_dbg(dev, "unsupported input data-mapping\n"); + return ret; + } + /* Locate the panel DT node. */ port = of_graph_get_port_by_id(dev->of_node, 1); if (!port) { @@ -84,6 +180,15 @@ static int lvds_encoder_probe(struct platform_device *pdev) return -ENXIO; } + ret = of_get_data_mapping(port, output_data_mappings, + ARRAY_SIZE(output_data_mappings), + &lvds_encoder->output_fmt); + if (ret) { + of_node_put(port); + dev_dbg(dev, "unsupported output data-mapping\n"); + return ret; + } + endpoint = of_get_child_by_name(port, "endpoint"); of_node_put(port); if (!endpoint) {