Sent from ProtonMail mobile
-------- Original Message -------- On Mar 10, 2021, 12:10, wrote:
Send dri-devel mailing list submissions to dri-devel@lists.freedesktop.org
To subscribe or unsubscribe via the World Wide Web, visit https://lists.freedesktop.org/mailman/listinfo/dri-devel or, via email, send a message with subject or body 'help' to dri-devel-request@lists.freedesktop.org
You can reach the person managing the list at dri-devel-owner@lists.freedesktop.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of dri-devel digest..."
Today's Topics:
- [PATCH v5 10/14] drm/bridge: imx: Add LDB driver helper
support (Liu Ying) 2. [PATCH v5 11/14] dt-bindings: display: bridge: Add i.MX8qm/qxp LVDS display bridge binding (Liu Ying)
Message: 1 Date: Wed, 10 Mar 2021 17:55:34 +0800 From: Liu Ying victor.liu@nxp.com To: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org Cc: airlied@linux.ie, daniel@ffwll.ch, robh+dt@kernel.org, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, mchehab@kernel.org, a.hajda@samsung.com, narmstrong@baylibre.com, Laurent.pinchart@ideasonboard.com, jonas@kwiboo.se, jernej.skrabec@siol.net, kishon@ti.com, vkoul@kernel.org, robert.foss@linaro.org, lee.jones@linaro.org Subject: [PATCH v5 10/14] drm/bridge: imx: Add LDB driver helper support Message-ID: 1615370138-5673-11-git-send-email-victor.liu@nxp.com Content-Type: text/plain
This patch adds a helper to support LDB drm bridge drivers for i.MX SoCs. Helper functions supported by this helper should implement common logics for all LDB modules embedded in i.MX SoCs.
Signed-off-by: Liu Ying victor.liu@nxp.com
v4->v5:
- Make imx-ldb-helper be a pure object to be linked with i.MX8qxp LDB bridge
driver and i.MX8qm LDB bridge driver. (Robert)
- Move 'imx_ldb_helper.h' to 'drivers/gpu/drm/bridge/imx/imx-ldb-helper.h'.
(Robert)
- s/__FSL_IMX_LDB__/__IMX_LDB_HELPER__/ for 'imx-ldb-helper.h'.
v3->v4:
- No change.
v2->v3:
- Call syscon_node_to_regmap() to get regmap instead of
syscon_regmap_lookup_by_phandle().
v1->v2:
- No change.
drivers/gpu/drm/bridge/imx/imx-ldb-helper.c | 232 ++++++++++++++++++++++++++++ drivers/gpu/drm/bridge/imx/imx-ldb-helper.h | 98 ++++++++++++ 2 files changed, 330 insertions(+) create mode 100644 drivers/gpu/drm/bridge/imx/imx-ldb-helper.c create mode 100644 drivers/gpu/drm/bridge/imx/imx-ldb-helper.h
diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c new file mode 100644 index 00000000..d01c4ff9 --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2012 Sascha Hauer, Pengutronix
- Copyright 2019,2020 NXP
- */
+#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/regmap.h>
+#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h>
+#include "imx-ldb-helper.h"
+bool ldb_channel_is_single_link(struct ldb_channel *ldb_ch) +{
- return ldb_ch->link_type == LDB_CH_SINGLE_LINK;
+}
+bool ldb_channel_is_split_link(struct ldb_channel *ldb_ch) +{
- return ldb_ch->link_type == LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS ||
- ldb_ch->link_type == LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS;
+}
+int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge,
- struct drm_bridge_state *bridge_state,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
+{
- struct ldb_channel *ldb_ch = bridge->driver_private;
- ldb_ch->in_bus_format = bridge_state->input_bus_cfg.format;
- ldb_ch->out_bus_format = bridge_state->output_bus_cfg.format;
- return 0;
+}
+void ldb_bridge_mode_set_helper(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- const struct drm_display_mode *adjusted_mode)
+{
- struct ldb_channel *ldb_ch = bridge->driver_private;
- struct ldb *ldb = ldb_ch->ldb;
- bool is_split = ldb_channel_is_split_link(ldb_ch);
- if (is_split)
- ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN;
- switch (ldb_ch->out_bus_format) {
- case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
- break;
- case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
- if (ldb_ch->chno == 0 || is_split)
- ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
- if (ldb_ch->chno == 1 || is_split)
- ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24;
- break;
- case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
- if (ldb_ch->chno == 0 || is_split)
- ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
- LDB_BIT_MAP_CH0_JEIDA;
- if (ldb_ch->chno == 1 || is_split)
- ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
- LDB_BIT_MAP_CH1_JEIDA;
- break;
- }
+}
+void ldb_bridge_enable_helper(struct drm_bridge *bridge) +{
- struct ldb_channel *ldb_ch = bridge->driver_private;
- struct ldb *ldb = ldb_ch->ldb;
- /*
- Platform specific bridge drivers should set ldb_ctrl properly
- for the enablement, so just write the ctrl_reg here.
- */
- regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl);
+}
+void ldb_bridge_disable_helper(struct drm_bridge *bridge) +{
- struct ldb_channel *ldb_ch = bridge->driver_private;
- struct ldb *ldb = ldb_ch->ldb;
- bool is_split = ldb_channel_is_split_link(ldb_ch);
- if (ldb_ch->chno == 0 || is_split)
- ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
- if (ldb_ch->chno == 1 || is_split)
- ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
- regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl);
+}
+int ldb_bridge_attach_helper(struct drm_bridge *bridge,
- enum drm_bridge_attach_flags flags)
+{
- struct ldb_channel *ldb_ch = bridge->driver_private;
- struct ldb *ldb = ldb_ch->ldb;
- if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
- DRM_DEV_ERROR(ldb->dev,
- "do not support creating a drm_connector\n");
- return -EINVAL;
- }
- if (!bridge->encoder) {
- DRM_DEV_ERROR(ldb->dev, "missing encoder\n");
- return -ENODEV;
- }
- return drm_bridge_attach(bridge->encoder,
- ldb_ch->next_bridge, bridge,
- DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+}
+int ldb_init_helper(struct ldb *ldb) +{
- struct device *dev = ldb->dev;
- struct device_node *np = dev->of_node;
- struct device_node *child;
- int ret;
- u32 i;
- ldb->regmap = syscon_node_to_regmap(np->parent);
- if (IS_ERR(ldb->regmap)) {
- ret = PTR_ERR(ldb->regmap);
- if (ret != -EPROBE_DEFER)
- DRM_DEV_ERROR(dev, "failed to get regmap: %d\n", ret);
- return ret;
- }
- for_each_available_child_of_node(np, child) {
- struct ldb_channel *ldb_ch;
- ret = of_property_read_u32(child, "reg", &i);
- if (ret || i > MAX_LDB_CHAN_NUM - 1) {
- ret = -EINVAL;
- DRM_DEV_ERROR(dev,
- "invalid channel node address: %u\n", i);
- of_node_put(child);
- return ret;
- }
- ldb_ch = ldb->channel[i];
- ldb_ch->ldb = ldb;
- ldb_ch->chno = i;
- ldb_ch->is_available = true;
- ldb_ch->np = child;
- ldb->available_ch_cnt++;
- }
- return 0;
+}
+int ldb_find_next_bridge_helper(struct ldb *ldb) +{
- struct device *dev = ldb->dev;
- struct ldb_channel *ldb_ch;
- int ret, i;
- for (i = 0; i < MAX_LDB_CHAN_NUM; i++) {
- ldb_ch = ldb->channel[i];
- if (!ldb_ch->is_available)
- continue;
- ret = drm_of_find_panel_or_bridge(ldb_ch->np, 1, 0,
- &ldb_ch->panel,
- &ldb_ch->next_bridge);
- if (ret) {
- if (ret != -EPROBE_DEFER)
- DRM_DEV_ERROR(dev,
- "failed to find panel or bridge: %d\n",
- ret);
- return ret;
- }
- if (ldb_ch->panel) {
- ldb_ch->next_bridge = devm_drm_panel_bridge_add(dev,
- ldb_ch->panel);
- if (IS_ERR(ldb_ch->next_bridge)) {
- ret = PTR_ERR(ldb_ch->next_bridge);
- DRM_DEV_ERROR(dev,
- "failed to add panel bridge: %d\n",
- ret);
- return ret;
- }
- }
- }
- return 0;
+}
+void ldb_add_bridge_helper(struct ldb *ldb,
- const struct drm_bridge_funcs *bridge_funcs)
+{
- struct ldb_channel *ldb_ch;
- int i;
- for (i = 0; i < MAX_LDB_CHAN_NUM; i++) {
- ldb_ch = ldb->channel[i];
- if (!ldb_ch->is_available)
- continue;
- ldb_ch->bridge.driver_private = ldb_ch;
- ldb_ch->bridge.funcs = bridge_funcs;
- ldb_ch->bridge.of_node = ldb_ch->np;
- drm_bridge_add(&ldb_ch->bridge);
- }
+}
+void ldb_remove_bridge_helper(struct ldb *ldb) +{
- struct ldb_channel *ldb_ch;
- int i;
- for (i = 0; i < MAX_LDB_CHAN_NUM; i++) {
- ldb_ch = ldb->channel[i];
- if (!ldb_ch->is_available)
- continue;
- drm_bridge_remove(&ldb_ch->bridge);
- }
+} diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.h b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.h new file mode 100644 index 00000000..748c378 --- /dev/null +++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0+ */
+/*
- Copyright 2019,2020 NXP
- */
+#ifndef __IMX_LDB_HELPER__ +#define __IMX_LDB_HELPER__
+#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/regmap.h>
+#include <drm/drm_atomic.h> +#include <drm/drm_bridge.h> +#include <drm/drm_device.h> +#include <drm/drm_encoder.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_panel.h>
+#define LDB_CH0_MODE_EN_TO_DI0 (1 << 0) +#define LDB_CH0_MODE_EN_TO_DI1 (3 << 0) +#define LDB_CH0_MODE_EN_MASK (3 << 0) +#define LDB_CH1_MODE_EN_TO_DI0 (1 << 2) +#define LDB_CH1_MODE_EN_TO_DI1 (3 << 2) +#define LDB_CH1_MODE_EN_MASK (3 << 2) +#define LDB_SPLIT_MODE_EN (1 << 4) +#define LDB_DATA_WIDTH_CH0_24 (1 << 5) +#define LDB_BIT_MAP_CH0_JEIDA (1 << 6) +#define LDB_DATA_WIDTH_CH1_24 (1 << 7) +#define LDB_BIT_MAP_CH1_JEIDA (1 << 8) +#define LDB_DI0_VS_POL_ACT_LOW (1 << 9) +#define LDB_DI1_VS_POL_ACT_LOW (1 << 10)
+#define MAX_LDB_CHAN_NUM 2
+enum ldb_channel_link_type {
- LDB_CH_SINGLE_LINK,
- LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS,
- LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS,
+};
+struct ldb;
+struct ldb_channel {
- struct ldb *ldb;
- struct drm_bridge bridge;
- struct drm_panel *panel;
- struct drm_bridge *next_bridge;
- struct device_node *np;
- u32 chno;
- bool is_available;
- u32 in_bus_format;
- u32 out_bus_format;
- enum ldb_channel_link_type link_type;
+};
+struct ldb {
- struct regmap *regmap;
- struct device *dev;
- struct ldb_channel *channel[MAX_LDB_CHAN_NUM];
- unsigned int ctrl_reg;
- u32 ldb_ctrl;
- unsigned int available_ch_cnt;
+};
+#define bridge_to_ldb_ch(b) container_of(b, struct ldb_channel, bridge)
+bool ldb_channel_is_single_link(struct ldb_channel *ldb_ch); +bool ldb_channel_is_split_link(struct ldb_channel *ldb_ch);
+int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge,
- struct drm_bridge_state *bridge_state,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state);
+void ldb_bridge_mode_set_helper(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- const struct drm_display_mode *adjusted_mode);
+void ldb_bridge_enable_helper(struct drm_bridge *bridge);
+void ldb_bridge_disable_helper(struct drm_bridge *bridge);
+int ldb_bridge_attach_helper(struct drm_bridge *bridge,
- enum drm_bridge_attach_flags flags);
+int ldb_init_helper(struct ldb *ldb);
+int ldb_find_next_bridge_helper(struct ldb *ldb);
+void ldb_add_bridge_helper(struct ldb *ldb,
- const struct drm_bridge_funcs *bridge_funcs);
+void ldb_remove_bridge_helper(struct ldb *ldb);
+#endif /* __IMX_LDB_HELPER__ */
2.7.4
Message: 2 Date: Wed, 10 Mar 2021 17:55:35 +0800 From: Liu Ying victor.liu@nxp.com To: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org Cc: airlied@linux.ie, daniel@ffwll.ch, robh+dt@kernel.org, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, mchehab@kernel.org, a.hajda@samsung.com, narmstrong@baylibre.com, Laurent.pinchart@ideasonboard.com, jonas@kwiboo.se, jernej.skrabec@siol.net, kishon@ti.com, vkoul@kernel.org, robert.foss@linaro.org, lee.jones@linaro.org Subject: [PATCH v5 11/14] dt-bindings: display: bridge: Add i.MX8qm/qxp LVDS display bridge binding Message-ID: 1615370138-5673-12-git-send-email-victor.liu@nxp.com Content-Type: text/plain
This patch adds bindings for i.MX8qm/qxp LVDS display bridge(LDB).
Reviewed-by: Rob Herring robh@kernel.org Signed-off-by: Liu Ying victor.liu@nxp.com
v4->v5:
- No change.
v3->v4:
- Add Rob's R-b tag.
v2->v3:
- Drop 'fsl,syscon' property. (Rob)
- Mention the CSR module controls LDB.
v1->v2:
- Use graph schema. (Laurent)
- Side note i.MX8qxp LDB official name 'pixel mapper'. (Laurent)
.../bindings/display/bridge/fsl,imx8qxp-ldb.yaml | 173 +++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-ldb.yaml
diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-ldb.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-ldb.yaml new file mode 100644 index 00000000..9454300 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-ldb.yaml @@ -0,0 +1,173 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/fsl,imx8qxp-ldb.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml#
+title: Freescale i.MX8qm/qxp LVDS Display Bridge
+maintainers:
- Liu Ying victor.liu@nxp.com
+description: |
- The Freescale i.MX8qm/qxp LVDS Display Bridge(LDB) has two channels.
- The i.MX8qm/qxp LDB is controlled by Control and Status Registers(CSR) module.
- The CSR module, as a system controller, contains the LDB's configuration
- registers.
- For i.MX8qxp LDB, each channel supports up to 24bpp parallel input color
- format and can map the input to VESA or JEIDA standards. The two channels
- cannot be used simultaneously, that is to say, the user should pick one of
- them to use. Two LDB channels from two LDB instances can work together in
- LDB split mode to support a dual link LVDS display. The channel indexes
- have to be different. Channel0 outputs odd pixels and channel1 outputs
- even pixels.
- For i.MX8qm LDB, each channel additionally supports up to 30bpp parallel
- input color format. The two channels can be used simultaneously, either
- in dual mode or split mode. In dual mode, the two channels output identical
- data. In split mode, channel0 outputs odd pixels and channel1 outputs even
- pixels.
- A side note is that i.MX8qm/qxp LDB is officially called pixel mapper in
- the SoC reference manuals. The pixel mapper uses logic of LDBs embedded in
- i.MX6qdl/sx SoCs, i.e., it is essentially based on them. To keep the naming
- consistency, this binding calls it LDB.
+properties:
- compatible:
- enum:
- fsl,imx8qm-ldb
- fsl,imx8qxp-ldb
- "#address-cells":
- const: 1
- "#size-cells":
- const: 0
- clocks:
- items:
- description: pixel clock
- description: bypass clock
- clock-names:
- items:
- const: pixel
- const: bypass
- power-domains:
- maxItems: 1
- fsl,companion-ldb:
- $ref: /schemas/types.yaml#/definitions/phandle
- description: |
- A phandle which points to companion LDB which is used in LDB split mode.
+patternProperties:
- "^channel@[0-1]$":
- type: object
- description: Represents a channel of LDB.
- properties:
- "#address-cells":
- const: 1
- "#size-cells":
- const: 0
- reg:
- description: The channel index.
- enum: [ 0, 1 ]
- phys:
- description: A phandle to the phy module representing the LVDS PHY.
- maxItems: 1
- phy-names:
- const: lvds_phy
- port@0:
- $ref: /schemas/graph.yaml#/properties/port
- description: Input port of the channel.
- port@1:
- $ref: /schemas/graph.yaml#/properties/port
- description: Output port of the channel.
- required:
- "#address-cells"
- "#size-cells"
- reg
- phys
- phy-names
- additionalProperties: false
+required:
- compatible
- "#address-cells"
- "#size-cells"
- clocks
- clock-names
- power-domains
- channel@0
- channel@1
+allOf:
- if:
- properties:
- compatible:
- contains:
- const: fsl,imx8qm-ldb
- then:
- properties:
- fsl,companion-ldb: false
+additionalProperties: false
+examples:
- |
- #include <dt-bindings/firmware/imx/rsrc.h>
- ldb {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,imx8qxp-ldb";
- clocks = <&clk IMX_SC_R_LVDS_0 IMX_SC_PM_CLK_MISC2>,
- <&clk IMX_SC_R_LVDS_0 IMX_SC_PM_CLK_BYPASS>;
- clock-names = "pixel", "bypass";
- power-domains = <&pd IMX_SC_R_LVDS_0>;
- channel@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- phys = <&mipi_lvds_0_phy>;
- phy-names = "lvds_phy";
- port@0 {
- reg = <0>;
- mipi_lvds_0_ldb_ch0_mipi_lvds_0_pxl2dpi: endpoint {
- remote-endpoint = <&mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch0>;
- };
- };
- };
- channel@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- phys = <&mipi_lvds_0_phy>;
- phy-names = "lvds_phy";
- port@0 {
- reg = <0>;
- mipi_lvds_0_ldb_ch1_mipi_lvds_0_pxl2dpi: endpoint {
- remote-endpoint = <&mipi_lvds_0_pxl2dpi_mipi_lvds_0_ldb_ch1>;
- };
- };
- };
- };
-- 2.7.4
Subject: Digest Footer
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
End of dri-devel Digest, Vol 132, Issue 196
dri-devel@lists.freedesktop.org