<br><br><br>Sent from ProtonMail mobile<br><br><br><br>-------- Original Message --------<br>On May 10, 2021, 10:49, < dri-devel-request@lists.freedesktop.org> wrote:<blockquote class="protonmail_quote"><br><p dir="ltr">Send dri-devel mailing list submissions to<br>
dri-devel@lists.freedesktop.org</p>
<p dir="ltr">To subscribe or unsubscribe via the World Wide Web, visit<br>
<a href="https://lists.freedesktop.org/mailman/listinfo/dri-devel">https://lists.freedesktop.org/mailman/listinfo/dri-devel</a><br>
or, via email, send a message with subject or body 'help' to<br>
dri-devel-request@lists.freedesktop.org</p>
<p dir="ltr">You can reach the person managing the list at<br>
dri-devel-owner@lists.freedesktop.org</p>
<p dir="ltr">When replying, please edit your Subject line so it is more specific<br>
than "Re: Contents of dri-devel digest..."<br></p>
<p dir="ltr">Today's Topics:</p>
<p dir="ltr">1. Re: [v3, 4/5] drm/connector: Add a helper to attach the<br>
colorspace property (Jernej ?krabec)<br>
2. Re: [PATCH v2] drm/amdgpu: Ensure that the modifier requested<br>
is supported by plane. (youling257)<br>
3. Re: [PATCH V4 2/2] drm/bridge: ti-sn65dsi83: Add TI SN65DSI83<br>
and SN65DSI84 driver (Frieder Schrempf)<br></p>
<p dir="ltr">----------------------------------------------------------------------</p>
<p dir="ltr">Message: 1<br>
Date: Fri, 07 May 2021 16:57:04 +0200<br>
From: Jernej ?krabec <jernej.skrabec@gmail.com><br>
To: dri-devel@lists.freedesktop.org, Daniel Vetter<br>
<daniel.vetter@intel.com>, David Airlie <airlied@linux.ie>, Maarten<br>
Lankhorst <maarten.lankhorst@linux.intel.com>, Thomas Zimmermann<br>
<tzimmermann@suse.de>, Maxime Ripard <maxime@cerno.tech>, Maxime<br>
Ripard <maxime@cerno.tech><br>
Cc: Tim Gover <tim.gover@raspberrypi.com>, Neil Armstrong<br>
<narmstrong@baylibre.com>, Andrzej Hajda <a.hajda@samsung.com>,<br>
Laurent Pinchart <Laurent.pinchart@ideasonboard.com>, Phil Elwell<br>
<phil@raspberrypi.com>, Dave Stevenson<br>
<dave.stevenson@raspberrypi.com>, amd-gfx@lists.freedesktop.org, Jonas<br>
Karlman <jonas@kwiboo.se>, Leo Li <<a href="http://sunpeng.li">sunpeng.li</a>@amd.com>,<br>
intel-gfx@lists.freedesktop.org, Rodrigo Vivi<br>
<rodrigo.vivi@intel.com>, Jernej Skrabec <jernej.skrabec@siol.net>,<br>
Dom Cobley <dom@raspberrypi.com>, linux-kernel@vger.kernel.org, Robert<br>
Foss <robert.foss@linaro.org>, Alex Deucher<br>
<alexander.deucher@amd.com>, Christian K?nig<br>
<christian.koenig@amd.com><br>
Subject: Re: [v3, 4/5] drm/connector: Add a helper to attach the<br>
colorspace property<br>
Message-ID: <2190160.Z2YBaczauS@jernej-laptop><br>
Content-Type: text/plain; charset="us-ascii"</p>
<p dir="ltr">Hi!</p>
<p dir="ltr">Dne petek, 30. april 2021 ob 11:44:50 CEST je Maxime Ripard napisal(a):<br>
> The intel driver uses the same logic to attach the Colorspace property<br>
> in multiple places and we'll need it in vc4 too. Let's move that common<br>
> code in a helper.<br>
><br>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech><br>
> ---<br>
><br>
> Changes from v2:<br>
> - Rebased on current drm-misc-next<br>
><br>
> Changes from v1:<br>
> - New patch<br>
> ---</p>
<p dir="ltr">Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com></p>
<p dir="ltr">Best regards,<br>
Jernej<br><br><br></p>
<p dir="ltr">------------------------------</p>
<p dir="ltr">Message: 2<br>
Date: Sun, 9 May 2021 20:17:41 +0800<br>
From: youling257 <youling257@gmail.com><br>
To: markyacoub@chromium.org<br>
Cc: amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org,<br>
michel@daenzer.net, daniel@fooishbar.org, bas@basnieuwenhuizen.nl,<br>
alexander.deucher@amd.com, markyacoub@google.com<br>
Subject: Re: [PATCH v2] drm/amdgpu: Ensure that the modifier requested<br>
is supported by plane.<br>
Message-ID: <20210509121741.25858-1-youling257@gmail.com></p>
<p dir="ltr">I using amd 3400g running with android-x86, this patch is a bad commit when i use android-x86 on amdgpu.<br></p>
<p dir="ltr">------------------------------</p>
<p dir="ltr">Message: 3<br>
Date: Mon, 10 May 2021 10:48:52 +0200<br>
From: Frieder Schrempf <frieder.schrempf@kontron.de><br>
To: Marek Vasut <marex@denx.de>, dri-devel@lists.freedesktop.org<br>
Cc: ch@denx.de, Linus Walleij <linus.walleij@linaro.org>, Douglas<br>
Anderson <dianders@chromium.org>, Jagan Teki<br>
<jagan@amarulasolutions.com>, Laurent Pinchart<br>
<laurent.pinchart@ideasonboard.com>, Loic Poulain<br>
<loic.poulain@linaro.org>, Philippe Schenker<br>
<philippe.schenker@toradex.com>, Sam Ravnborg <sam@ravnborg.org>,<br>
Stephen Boyd <swboyd@chromium.org>, Valentin Raevsky<br>
<valentin@compulab.co.il><br>
Subject: Re: [PATCH V4 2/2] drm/bridge: ti-sn65dsi83: Add TI SN65DSI83<br>
and SN65DSI84 driver<br>
Message-ID: <645eb495-e30e-ed70-f01a-9f3f382f2a20@kontron.de><br>
Content-Type: text/plain; charset=utf-8</p>
<p dir="ltr">On 08.05.21 22:22, Marek Vasut wrote:<br>
> Add driver for TI SN65DSI83 Single-link DSI to Single-link LVDS bridge<br>
> and TI SN65DSI84 Single-link DSI to Dual-link or 2x Single-link LVDS<br>
> bridge. TI SN65DSI85 is unsupported due to lack of hardware to test on,<br>
> but easy to add.<br>
><br>
> The driver operates the chip via I2C bus. Currently the LVDS clock are<br>
> always derived from DSI clock lane, which is the usual mode of operation.<br>
> Support for clock from external oscillator is not implemented, but it is<br>
> easy to add if ever needed. Only RGB888 pixel format is implemented, the<br>
> LVDS666 is not supported, but could be added if needed.<br>
><br>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org><br>
> Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de><br>
> Tested-by: Frieder Schrempf <frieder.schrempf@kontron.de><br>
> Signed-off-by: Marek Vasut <marex@denx.de><br>
> Cc: Douglas Anderson <dianders@chromium.org><br>
> Cc: Jagan Teki <jagan@amarulasolutions.com><br>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com><br>
> Cc: Linus Walleij <linus.walleij@linaro.org><br>
> Cc: Loic Poulain <loic.poulain@linaro.org><br>
> Cc: Philippe Schenker <philippe.schenker@toradex.com><br>
> Cc: Sam Ravnborg <sam@ravnborg.org><br>
> Cc: Stephen Boyd <swboyd@chromium.org><br>
> Cc: Valentin Raevsky <valentin@compulab.co.il><br>
> To: dri-devel@lists.freedesktop.org<br>
> ---<br>
> V2: - Use dev_err_probe()<br>
> - Set REG_RC_RESET as volatile<br>
> - Wait for PLL stabilization by polling REG_RC_LVDS_PLL<br>
> - Use ctx->mode = *adj instead of *mode in sn65dsi83_mode_set<br>
> - Add tested DSI84 support in dual-link mode<br>
> - Correctly set VCOM<br>
> - Fill in missing DSI CHB and LVDS CHB bits from DSI84 and DSI85<br>
> datasheets, with that all the reserved bits make far more sense<br>
> as the DSI83 and DSI84 seems to be reduced version of DSI85<br>
> V3: - Handle the dual-link LVDS with two port panel or bridge<br>
> V4: - Add RB from Linus Walleij<br>
> - Rename REG_DSI_LANE_LVDS_LINK_CFG_DUAL to<br>
> REG_DSI_LANE_DSI_CHANNEL_MODE_SINGLE and fill in the remaining<br>
> DSI link options from DSI85 datasheet. DSI85 can do dual and 2x<br>
> single DSI mode, but DSI85 is currently unsupported by the<br>
> driver. Add a comment about DSI85, so that all the places which<br>
> need to be adjusted for DSI85 are marked accordingly.<br>
> - Add REG_DSI_LANE_LEFT_RIGHT_PIXELS bit for DSI<br>
> - Add handling for JEIDA18/JEIDA24/SPWG24 LVDS formats. Use SPWG24<br>
> as fallback on output bridges until they are all fixed.<br>
> - Patch DSI bus format to fixed RGB888_1X24 instead of passing<br>
> through the LVDS bus format.</p>
<p dir="ltr">I just want to report that v4 now handles my panel with MEDIA_BUS_FMT_RGB888_1X7X4_SPWG correctly. Thanks for coming up with this solution. Looks good to me.</p>
<p dir="ltr">> ---<br>
> drivers/gpu/drm/bridge/Kconfig | 10 +<br>
> drivers/gpu/drm/bridge/Makefile | 1 +<br>
> drivers/gpu/drm/bridge/ti-sn65dsi83.c | 698 ++++++++++++++++++++++++++<br>
> 3 files changed, 709 insertions(+)<br>
> create mode 100644 drivers/gpu/drm/bridge/ti-sn65dsi83.c<br>
><br>
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig<br>
> index e83b8ad0d71b..32204c5f25b7 100644<br>
> --- a/drivers/gpu/drm/bridge/Kconfig<br>
> +++ b/drivers/gpu/drm/bridge/Kconfig<br>
> @@ -278,6 +278,16 @@ config DRM_TI_TFP410<br>
> help<br>
> Texas Instruments TFP410 DVI/HDMI Transmitter driver<br>
><br>
> +config DRM_TI_SN65DSI83<br>
> + tristate "TI SN65DSI83 and SN65DSI84 DSI to LVDS bridge"<br>
> + depends on OF<br>
> + select DRM_KMS_HELPER<br>
> + select REGMAP_I2C<br>
> + select DRM_PANEL<br>
> + select DRM_MIPI_DSI<br>
> + help<br>
> + Texas Instruments SN65DSI83 and SN65DSI84 DSI to LVDS Bridge driver<br>
> +<br>
> config DRM_TI_SN65DSI86<br>
> tristate "TI SN65DSI86 DSI to eDP bridge"<br>
> depends on OF<br>
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile<br>
> index b00f3b2ad572..7bb4c9df0415 100644<br>
> --- a/drivers/gpu/drm/bridge/Makefile<br>
> +++ b/drivers/gpu/drm/bridge/Makefile<br>
> @@ -24,6 +24,7 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o<br>
> obj-$(CONFIG_DRM_TOSHIBA_TC358768) += tc358768.o<br>
> obj-$(CONFIG_DRM_TOSHIBA_TC358775) += tc358775.o<br>
> obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/<br>
> +obj-$(CONFIG_DRM_TI_SN65DSI83) += ti-sn65dsi83.o<br>
> obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o<br>
> obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o<br>
> obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o<br>
> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c<br>
> new file mode 100644<br>
> index 000000000000..1a0a71fbe91d<br>
> --- /dev/null<br>
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c<br>
> @@ -0,0 +1,698 @@<br>
> +// SPDX-License-Identifier: GPL-2.0<br>
> +/*<br>
> + * TI SN65DSI83,84,85 driver<br>
> + *<br>
> + * Currently supported:<br>
> + * - SN65DSI83<br>
> + * = 1x Single-link DSI ~ 1x Single-link LVDS<br>
> + * - Supported<br>
> + * - Single-link LVDS mode tested<br>
> + * - SN65DSI84<br>
> + * = 1x Single-link DSI ~ 2x Single-link or 1x Dual-link LVDS<br>
> + * - Supported<br>
> + * - Dual-link LVDS mode tested<br>
> + * - 2x Single-link LVDS mode unsupported<br>
> + * (should be easy to add by someone who has the HW)<br>
> + * - SN65DSI85<br>
> + * = 2x Single-link or 1x Dual-link DSI ~ 2x Single-link or 1x Dual-link LVDS<br>
> + * - Unsupported<br>
> + * (should be easy to add by someone who has the HW)<br>
> + *<br>
> + * Copyright (C) 2021 Marek Vasut <marex@denx.de><br>
> + *<br>
> + * Based on previous work of:<br>
> + * Valentin Raevsky <valentin@compulab.co.il><br>
> + * Philippe Schenker <philippe.schenker@toradex.com><br>
> + */<br>
> +<br>
> +#include <linux/bits.h><br>
> +#include <linux/clk.h><br>
> +#include <linux/gpio/consumer.h><br>
> +#include <linux/i2c.h><br>
> +#include <linux/module.h><br>
> +#include <linux/of_device.h><br>
> +#include <linux/of_graph.h><br>
> +#include <linux/regmap.h><br>
> +<br>
> +#include <drm/drm_atomic_helper.h><br>
> +#include <drm/drm_bridge.h><br>
> +#include <drm/drm_mipi_dsi.h><br>
> +#include <drm/drm_of.h><br>
> +#include <drm/drm_panel.h><br>
> +#include <drm/drm_print.h><br>
> +#include <drm/drm_probe_helper.h><br>
> +<br>
> +/* ID registers */<br>
> +#define REG_ID(n) (0x00 + (n))<br>
> +/* Reset and clock registers */<br>
> +#define REG_RC_RESET 0x09<br>
> +#define REG_RC_RESET_SOFT_RESET BIT(0)<br>
> +#define REG_RC_LVDS_PLL 0x0a<br>
> +#define REG_RC_LVDS_PLL_PLL_EN_STAT BIT(7)<br>
> +#define REG_RC_LVDS_PLL_LVDS_CLK_RANGE(n) (((n) & 0x7) << 1)<br>
> +#define REG_RC_LVDS_PLL_HS_CLK_SRC_DPHY BIT(0)<br>
> +#define REG_RC_DSI_CLK 0x0b<br>
> +#define REG_RC_DSI_CLK_DSI_CLK_DIVIDER(n) (((n) & 0x1f) << 3)<br>
> +#define REG_RC_DSI_CLK_REFCLK_MULTIPLIER(n) ((n) & 0x3)<br>
> +#define REG_RC_PLL_EN 0x0d<br>
> +#define REG_RC_PLL_EN_PLL_EN BIT(0)<br>
> +/* DSI registers */<br>
> +#define REG_DSI_LANE 0x10<br>
> +#define REG_DSI_LANE_LEFT_RIGHT_PIXELS BIT(7) /* DSI85-only */<br>
> +#define REG_DSI_LANE_DSI_CHANNEL_MODE_DUAL 0 /* DSI85-only */<br>
> +#define REG_DSI_LANE_DSI_CHANNEL_MODE_2SINGLE BIT(6) /* DSI85-only */<br>
> +#define REG_DSI_LANE_DSI_CHANNEL_MODE_SINGLE BIT(5)<br>
> +#define REG_DSI_LANE_CHA_DSI_LANES(n) (((n) & 0x3) << 3)<br>
> +#define REG_DSI_LANE_CHB_DSI_LANES(n) (((n) & 0x3) << 1)<br>
> +#define REG_DSI_LANE_SOT_ERR_TOL_DIS BIT(0)<br>
> +#define REG_DSI_EQ 0x11<br>
> +#define REG_DSI_EQ_CHA_DSI_DATA_EQ(n) (((n) & 0x3) << 6)<br>
> +#define REG_DSI_EQ_CHA_DSI_CLK_EQ(n) (((n) & 0x3) << 2)<br>
> +#define REG_DSI_CLK 0x12<br>
> +#define REG_DSI_CLK_CHA_DSI_CLK_RANGE(n) ((n) & 0xff)<br>
> +/* LVDS registers */<br>
> +#define REG_LVDS_FMT 0x18<br>
> +#define REG_LVDS_FMT_DE_NEG_POLARITY BIT(7)<br>
> +#define REG_LVDS_FMT_HS_NEG_POLARITY BIT(6)<br>
> +#define REG_LVDS_FMT_VS_NEG_POLARITY BIT(5)<br>
> +#define REG_LVDS_FMT_LVDS_LINK_CFG BIT(4) /* 0:AB 1:A-only */<br>
> +#define REG_LVDS_FMT_CHA_24BPP_MODE BIT(3)<br>
> +#define REG_LVDS_FMT_CHB_24BPP_MODE BIT(2)<br>
> +#define REG_LVDS_FMT_CHA_24BPP_FORMAT1 BIT(1)<br>
> +#define REG_LVDS_FMT_CHB_24BPP_FORMAT1 BIT(0)<br>
> +#define REG_LVDS_VCOM 0x19<br>
> +#define REG_LVDS_VCOM_CHA_LVDS_VOCM BIT(6)<br>
> +#define REG_LVDS_VCOM_CHB_LVDS_VOCM BIT(4)<br>
> +#define REG_LVDS_VCOM_CHA_LVDS_VOD_SWING(n) (((n) & 0x3) << 2)<br>
> +#define REG_LVDS_VCOM_CHB_LVDS_VOD_SWING(n) ((n) & 0x3)<br>
> +#define REG_LVDS_LANE 0x1a<br>
> +#define REG_LVDS_LANE_EVEN_ODD_SWAP BIT(6)<br>
> +#define REG_LVDS_LANE_CHA_REVERSE_LVDS BIT(5)<br>
> +#define REG_LVDS_LANE_CHB_REVERSE_LVDS BIT(4)<br>
> +#define REG_LVDS_LANE_CHA_LVDS_TERM BIT(1)<br>
> +#define REG_LVDS_LANE_CHB_LVDS_TERM BIT(0)<br>
> +#define REG_LVDS_CM 0x1b<br>
> +#define REG_LVDS_CM_CHA_LVDS_CM_ADJUST(n) (((n) & 0x3) << 4)<br>
> +#define REG_LVDS_CM_CHB_LVDS_CM_ADJUST(n) ((n) & 0x3)<br>
> +/* Video registers */<br>
> +#define REG_VID_CHA_ACTIVE_LINE_LENGTH_LOW 0x20<br>
> +#define REG_VID_CHA_ACTIVE_LINE_LENGTH_HIGH 0x21<br>
> +#define REG_VID_CHA_VERTICAL_DISPLAY_SIZE_LOW 0x24<br>
> +#define REG_VID_CHA_VERTICAL_DISPLAY_SIZE_HIGH 0x25<br>
> +#define REG_VID_CHA_SYNC_DELAY_LOW 0x28<br>
> +#define REG_VID_CHA_SYNC_DELAY_HIGH 0x29<br>
> +#define REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW 0x2c<br>
> +#define REG_VID_CHA_HSYNC_PULSE_WIDTH_HIGH 0x2d<br>
> +#define REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW 0x30<br>
> +#define REG_VID_CHA_VSYNC_PULSE_WIDTH_HIGH 0x31<br>
> +#define REG_VID_CHA_HORIZONTAL_BACK_PORCH 0x34<br>
> +#define REG_VID_CHA_VERTICAL_BACK_PORCH 0x36<br>
> +#define REG_VID_CHA_HORIZONTAL_FRONT_PORCH 0x38<br>
> +#define REG_VID_CHA_VERTICAL_FRONT_PORCH 0x3a<br>
> +#define REG_VID_CHA_TEST_PATTERN 0x3c<br>
> +/* IRQ registers */<br>
> +#define REG_IRQ_GLOBAL 0xe0<br>
> +#define REG_IRQ_GLOBAL_IRQ_EN BIT(0)<br>
> +#define REG_IRQ_EN 0xe1<br>
> +#define REG_IRQ_EN_CHA_SYNCH_ERR_EN BIT(7)<br>
> +#define REG_IRQ_EN_CHA_CRC_ERR_EN BIT(6)<br>
> +#define REG_IRQ_EN_CHA_UNC_ECC_ERR_EN BIT(5)<br>
> +#define REG_IRQ_EN_CHA_COR_ECC_ERR_EN BIT(4)<br>
> +#define REG_IRQ_EN_CHA_LLP_ERR_EN BIT(3)<br>
> +#define REG_IRQ_EN_CHA_SOT_BIT_ERR_EN BIT(2)<br>
> +#define REG_IRQ_EN_CHA_PLL_UNLOCK_EN BIT(0)<br>
> +#define REG_IRQ_STAT 0xe5<br>
> +#define REG_IRQ_STAT_CHA_SYNCH_ERR BIT(7)<br>
> +#define REG_IRQ_STAT_CHA_CRC_ERR BIT(6)<br>
> +#define REG_IRQ_STAT_CHA_UNC_ECC_ERR BIT(5)<br>
> +#define REG_IRQ_STAT_CHA_COR_ECC_ERR BIT(4)<br>
> +#define REG_IRQ_STAT_CHA_LLP_ERR BIT(3)<br>
> +#define REG_IRQ_STAT_CHA_SOT_BIT_ERR BIT(2)<br>
> +#define REG_IRQ_STAT_CHA_PLL_UNLOCK BIT(0)<br>
> +<br>
> +enum sn65dsi83_model {<br>
> + MODEL_SN65DSI83,<br>
> + MODEL_SN65DSI84,<br>
> +};<br>
> +<br>
> +struct sn65dsi83 {<br>
> + struct drm_bridge bridge;<br>
> + struct drm_display_mode mode;<br>
> + struct device *dev;<br>
> + struct regmap *regmap;<br>
> + struct device_node *host_node;<br>
> + struct mipi_dsi_device *dsi;<br>
> + struct drm_bridge *panel_bridge;<br>
> + struct gpio_desc *enable_gpio;<br>
> + int dsi_lanes;<br>
> + bool lvds_dual_link;<br>
> + bool lvds_dual_link_even_odd_swap;<br>
> + bool lvds_format_24bpp;<br>
> + bool lvds_format_jeida;<br>
> +};<br>
> +<br>
> +static const struct regmap_range sn65dsi83_readable_ranges[] = {<br>
> + regmap_reg_range(REG_ID(0), REG_ID(8)),<br>
> + regmap_reg_range(REG_RC_LVDS_PLL, REG_RC_DSI_CLK),<br>
> + regmap_reg_range(REG_RC_PLL_EN, REG_RC_PLL_EN),<br>
> + regmap_reg_range(REG_DSI_LANE, REG_DSI_CLK),<br>
> + regmap_reg_range(REG_LVDS_FMT, REG_LVDS_CM),<br>
> + regmap_reg_range(REG_VID_CHA_ACTIVE_LINE_LENGTH_LOW,<br>
> + REG_VID_CHA_ACTIVE_LINE_LENGTH_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_VERTICAL_DISPLAY_SIZE_LOW,<br>
> + REG_VID_CHA_VERTICAL_DISPLAY_SIZE_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_SYNC_DELAY_LOW,<br>
> + REG_VID_CHA_SYNC_DELAY_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW,<br>
> + REG_VID_CHA_HSYNC_PULSE_WIDTH_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW,<br>
> + REG_VID_CHA_VSYNC_PULSE_WIDTH_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_HORIZONTAL_BACK_PORCH,<br>
> + REG_VID_CHA_HORIZONTAL_BACK_PORCH),<br>
> + regmap_reg_range(REG_VID_CHA_VERTICAL_BACK_PORCH,<br>
> + REG_VID_CHA_VERTICAL_BACK_PORCH),<br>
> + regmap_reg_range(REG_VID_CHA_HORIZONTAL_FRONT_PORCH,<br>
> + REG_VID_CHA_HORIZONTAL_FRONT_PORCH),<br>
> + regmap_reg_range(REG_VID_CHA_VERTICAL_FRONT_PORCH,<br>
> + REG_VID_CHA_VERTICAL_FRONT_PORCH),<br>
> + regmap_reg_range(REG_VID_CHA_TEST_PATTERN, REG_VID_CHA_TEST_PATTERN),<br>
> + regmap_reg_range(REG_IRQ_GLOBAL, REG_IRQ_EN),<br>
> + regmap_reg_range(REG_IRQ_STAT, REG_IRQ_STAT),<br>
> +};<br>
> +<br>
> +static const struct regmap_access_table sn65dsi83_readable_table = {<br>
> + .yes_ranges = sn65dsi83_readable_ranges,<br>
> + .n_yes_ranges = ARRAY_SIZE(sn65dsi83_readable_ranges),<br>
> +};<br>
> +<br>
> +static const struct regmap_range sn65dsi83_writeable_ranges[] = {<br>
> + regmap_reg_range(REG_RC_RESET, REG_RC_DSI_CLK),<br>
> + regmap_reg_range(REG_RC_PLL_EN, REG_RC_PLL_EN),<br>
> + regmap_reg_range(REG_DSI_LANE, REG_DSI_CLK),<br>
> + regmap_reg_range(REG_LVDS_FMT, REG_LVDS_CM),<br>
> + regmap_reg_range(REG_VID_CHA_ACTIVE_LINE_LENGTH_LOW,<br>
> + REG_VID_CHA_ACTIVE_LINE_LENGTH_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_VERTICAL_DISPLAY_SIZE_LOW,<br>
> + REG_VID_CHA_VERTICAL_DISPLAY_SIZE_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_SYNC_DELAY_LOW,<br>
> + REG_VID_CHA_SYNC_DELAY_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW,<br>
> + REG_VID_CHA_HSYNC_PULSE_WIDTH_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW,<br>
> + REG_VID_CHA_VSYNC_PULSE_WIDTH_HIGH),<br>
> + regmap_reg_range(REG_VID_CHA_HORIZONTAL_BACK_PORCH,<br>
> + REG_VID_CHA_HORIZONTAL_BACK_PORCH),<br>
> + regmap_reg_range(REG_VID_CHA_VERTICAL_BACK_PORCH,<br>
> + REG_VID_CHA_VERTICAL_BACK_PORCH),<br>
> + regmap_reg_range(REG_VID_CHA_HORIZONTAL_FRONT_PORCH,<br>
> + REG_VID_CHA_HORIZONTAL_FRONT_PORCH),<br>
> + regmap_reg_range(REG_VID_CHA_VERTICAL_FRONT_PORCH,<br>
> + REG_VID_CHA_VERTICAL_FRONT_PORCH),<br>
> + regmap_reg_range(REG_VID_CHA_TEST_PATTERN, REG_VID_CHA_TEST_PATTERN),<br>
> + regmap_reg_range(REG_IRQ_GLOBAL, REG_IRQ_EN),<br>
> + regmap_reg_range(REG_IRQ_STAT, REG_IRQ_STAT),<br>
> +};<br>
> +<br>
> +static const struct regmap_access_table sn65dsi83_writeable_table = {<br>
> + .yes_ranges = sn65dsi83_writeable_ranges,<br>
> + .n_yes_ranges = ARRAY_SIZE(sn65dsi83_writeable_ranges),<br>
> +};<br>
> +<br>
> +static const struct regmap_range sn65dsi83_volatile_ranges[] = {<br>
> + regmap_reg_range(REG_RC_RESET, REG_RC_RESET),<br>
> + regmap_reg_range(REG_RC_LVDS_PLL, REG_RC_LVDS_PLL),<br>
> + regmap_reg_range(REG_IRQ_STAT, REG_IRQ_STAT),<br>
> +};<br>
> +<br>
> +static const struct regmap_access_table sn65dsi83_volatile_table = {<br>
> + .yes_ranges = sn65dsi83_volatile_ranges,<br>
> + .n_yes_ranges = ARRAY_SIZE(sn65dsi83_volatile_ranges),<br>
> +};<br>
> +<br>
> +static const struct regmap_config sn65dsi83_regmap_config = {<br>
> + .reg_bits = 8,<br>
> + .val_bits = 8,<br>
> + .rd_table = &sn65dsi83_readable_table,<br>
> + .wr_table = &sn65dsi83_writeable_table,<br>
> + .volatile_table = &sn65dsi83_volatile_table,<br>
> + .cache_type = REGCACHE_RBTREE,<br>
> + .max_register = REG_IRQ_STAT,<br>
> +};<br>
> +<br>
> +static struct sn65dsi83 *bridge_to_sn65dsi83(struct drm_bridge *bridge)<br>
> +{<br>
> + return container_of(bridge, struct sn65dsi83, bridge);<br>
> +}<br>
> +<br>
> +static int sn65dsi83_attach(struct drm_bridge *bridge,<br>
> + enum drm_bridge_attach_flags flags)<br>
> +{<br>
> + struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);<br>
> + struct device *dev = ctx->dev;<br>
> + struct mipi_dsi_device *dsi;<br>
> + struct mipi_dsi_host *host;<br>
> + int ret = 0;<br>
> +<br>
> + const struct mipi_dsi_device_info info = {<br>
> + .type = "sn65dsi83",<br>
> + .channel = 0,<br>
> + .node = NULL,<br>
> + };<br>
> +<br>
> + host = of_find_mipi_dsi_host_by_node(ctx->host_node);<br>
> + if (!host) {<br>
> + dev_err(dev, "failed to find dsi host\n");<br>
> + return -EPROBE_DEFER;<br>
> + }<br>
> +<br>
> + dsi = mipi_dsi_device_register_full(host, &info);<br>
> + if (IS_ERR(dsi)) {<br>
> + return dev_err_probe(dev, PTR_ERR(dsi),<br>
> + "failed to create dsi device\n");<br>
> + }<br>
> +<br>
> + ctx->dsi = dsi;<br>
> +<br>
> + dsi->lanes = ctx->dsi_lanes;<br>
> + dsi->format = MIPI_DSI_FMT_RGB888;<br>
> + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST;<br>
> +<br>
> + ret = mipi_dsi_attach(dsi);<br>
> + if (ret < 0) {<br>
> + dev_err(dev, "failed to attach dsi to host\n");<br>
> + goto err_dsi_attach;<br>
> + }<br>
> +<br>
> + return drm_bridge_attach(bridge->encoder, ctx->panel_bridge,<br>
> + &ctx->bridge, flags);<br>
> +<br>
> +err_dsi_attach:<br>
> + mipi_dsi_device_unregister(dsi);<br>
> + return ret;<br>
> +}<br>
> +<br>
> +static void sn65dsi83_pre_enable(struct drm_bridge *bridge)<br>
> +{<br>
> + struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);<br>
> +<br>
> + /*<br>
> + * Reset the chip, pull EN line low for t_reset=10ms,<br>
> + * then high for t_en=1ms.<br>
> + */<br>
> + regcache_mark_dirty(ctx->regmap);<br>
> + gpiod_set_value(ctx->enable_gpio, 0);<br>
> + usleep_range(10000, 11000);<br>
> + gpiod_set_value(ctx->enable_gpio, 1);<br>
> + usleep_range(1000, 1100);<br>
> +}<br>
> +<br>
> +static u8 sn65dsi83_get_lvds_range(struct sn65dsi83 *ctx)<br>
> +{<br>
> + /*<br>
> + * The encoding of the LVDS_CLK_RANGE is as follows:<br>
> + * 000 - 25 MHz <= LVDS_CLK < 37.5 MHz<br>
> + * 001 - 37.5 MHz <= LVDS_CLK < 62.5 MHz<br>
> + * 010 - 62.5 MHz <= LVDS_CLK < 87.5 MHz<br>
> + * 011 - 87.5 MHz <= LVDS_CLK < 112.5 MHz<br>
> + * 100 - 112.5 MHz <= LVDS_CLK < 137.5 MHz<br>
> + * 101 - 137.5 MHz <= LVDS_CLK <= 154 MHz<br>
> + * which is a range of 12.5MHz..162.5MHz in 50MHz steps, except that<br>
> + * the ends of the ranges are clamped to the supported range. Since<br>
> + * sn65dsi83_mode_valid() already filters the valid modes and limits<br>
> + * the clock to 25..154 MHz, the range calculation can be simplified<br>
> + * as follows:<br>
> + */<br>
> + int mode_clock = ctx->mode.clock;<br>
> +<br>
> + if (ctx->lvds_dual_link)<br>
> + mode_clock /= 2;<br>
> +<br>
> + return (mode_clock - 12500) / 25000;<br>
> +}<br>
> +<br>
> +static u8 sn65dsi83_get_dsi_range(struct sn65dsi83 *ctx)<br>
> +{<br>
> + /*<br>
> + * The encoding of the CHA_DSI_CLK_RANGE is as follows:<br>
> + * 0x00 through 0x07 - Reserved<br>
> + * 0x08 - 40 <= DSI_CLK < 45 MHz<br>
> + * 0x09 - 45 <= DSI_CLK < 50 MHz<br>
> + * ...<br>
> + * 0x63 - 495 <= DSI_CLK < 500 MHz<br>
> + * 0x64 - 500 MHz<br>
> + * 0x65 through 0xFF - Reserved<br>
> + * which is DSI clock in 5 MHz steps, clamped to 40..500 MHz.<br>
> + * The DSI clock are calculated as:<br>
> + * DSI_CLK = mode clock * bpp / dsi_data_lanes / 2<br>
> + * the 2 is there because the bus is DDR.<br>
> + */<br>
> + return DIV_ROUND_UP(clamp((unsigned int)ctx->mode.clock *<br>
> + mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) /<br>
> + ctx->dsi_lanes / 2, 40000U, 500000U), 5000U);<br>
> +}<br>
> +<br>
> +static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)<br>
> +{<br>
> + /* The divider is (DSI_CLK / LVDS_CLK) - 1, which really is: */<br>
> + unsigned int dsi_div = mipi_dsi_pixel_format_to_bpp(ctx->dsi->format);<br>
> +<br>
> + dsi_div /= ctx->dsi_lanes;<br>
> +<br>
> + if (!ctx->lvds_dual_link)<br>
> + dsi_div /= 2;<br>
> +<br>
> + return dsi_div - 1;<br>
> +}<br>
> +<br>
> +static void sn65dsi83_enable(struct drm_bridge *bridge)<br>
> +{<br>
> + struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);<br>
> + unsigned int pval;<br>
> + u16 val;<br>
> + int ret;<br>
> +<br>
> + /* Clear reset, disable PLL */<br>
> + regmap_write(ctx->regmap, REG_RC_RESET, 0x00);<br>
> + regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);<br>
> +<br>
> + /* Reference clock derived from DSI link clock. */<br>
> + regmap_write(ctx->regmap, REG_RC_LVDS_PLL,<br>
> + REG_RC_LVDS_PLL_LVDS_CLK_RANGE(sn65dsi83_get_lvds_range(ctx)) |<br>
> + REG_RC_LVDS_PLL_HS_CLK_SRC_DPHY);<br>
> + regmap_write(ctx->regmap, REG_DSI_CLK,<br>
> + REG_DSI_CLK_CHA_DSI_CLK_RANGE(sn65dsi83_get_dsi_range(ctx)));<br>
> + regmap_write(ctx->regmap, REG_RC_DSI_CLK,<br>
> + REG_RC_DSI_CLK_DSI_CLK_DIVIDER(sn65dsi83_get_dsi_div(ctx)));<br>
> +<br>
> + /* Set number of DSI lanes and LVDS link config. */<br>
> + regmap_write(ctx->regmap, REG_DSI_LANE,<br>
> + REG_DSI_LANE_DSI_CHANNEL_MODE_SINGLE |<br>
> + REG_DSI_LANE_CHA_DSI_LANES(~(ctx->dsi_lanes - 1)) |<br>
> + /* CHB is DSI85-only, set to default on DSI83/DSI84 */<br>
> + REG_DSI_LANE_CHB_DSI_LANES(3));<br>
> + /* No equalization. */<br>
> + regmap_write(ctx->regmap, REG_DSI_EQ, 0x00);<br>
> +<br>
> + /* Set up sync signal polarity. */<br>
> + val = (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC ?<br>
> + REG_LVDS_FMT_HS_NEG_POLARITY : 0) |<br>
> + (ctx->mode.flags & DRM_MODE_FLAG_NVSYNC ?<br>
> + REG_LVDS_FMT_VS_NEG_POLARITY : 0);<br>
> +<br>
> + /* Set up bits-per-pixel, 18bpp or 24bpp. */<br>
> + if (ctx->lvds_format_24bpp) {<br>
> + val |= REG_LVDS_FMT_CHA_24BPP_MODE;<br>
> + if (ctx->lvds_dual_link)<br>
> + val |= REG_LVDS_FMT_CHB_24BPP_MODE;<br>
> + }<br>
> +<br>
> + /* Set up LVDS format, JEIDA/Format 1 or SPWG/Format 2 */<br>
> + if (ctx->lvds_format_jeida) {<br>
> + val |= REG_LVDS_FMT_CHA_24BPP_FORMAT1;<br>
> + if (ctx->lvds_dual_link)<br>
> + val |= REG_LVDS_FMT_CHB_24BPP_FORMAT1;<br>
> + }<br>
> +<br>
> + /* Set up LVDS output config (DSI84,DSI85) */<br>
> + if (!ctx->lvds_dual_link)<br>
> + val |= REG_LVDS_FMT_LVDS_LINK_CFG;<br>
> +<br>
> + regmap_write(ctx->regmap, REG_LVDS_FMT, val);<br>
> + regmap_write(ctx->regmap, REG_LVDS_VCOM, 0x05);<br>
> + regmap_write(ctx->regmap, REG_LVDS_LANE,<br>
> + (ctx->lvds_dual_link_even_odd_swap ?<br>
> + REG_LVDS_LANE_EVEN_ODD_SWAP : 0) |<br>
> + REG_LVDS_LANE_CHA_LVDS_TERM |<br>
> + REG_LVDS_LANE_CHB_LVDS_TERM);<br>
> + regmap_write(ctx->regmap, REG_LVDS_CM, 0x00);<br>
> +<br>
> + regmap_bulk_write(ctx->regmap, REG_VID_CHA_ACTIVE_LINE_LENGTH_LOW,<br>
> + &ctx->mode.hdisplay, 2);<br>
> + regmap_bulk_write(ctx->regmap, REG_VID_CHA_VERTICAL_DISPLAY_SIZE_LOW,<br>
> + &ctx->mode.vdisplay, 2);<br>
> + val = 32 + 1; /* 32 + 1 pixel clock to ensure proper operation */<br>
> + regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &val, 2);<br>
> + val = ctx->mode.hsync_end - ctx->mode.hsync_start;<br>
> + regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW,<br>
> + &val, 2);<br>
> + val = ctx->mode.vsync_end - ctx->mode.vsync_start;<br>
> + regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW,<br>
> + &val, 2);<br>
> + regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH,<br>
> + ctx->mode.htotal - ctx->mode.hsync_end);<br>
> + regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH,<br>
> + ctx->mode.vtotal - ctx->mode.vsync_end);<br>
> + regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH,<br>
> + ctx->mode.hsync_start - ctx->mode.hdisplay);<br>
> + regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH,<br>
> + ctx->mode.vsync_start - ctx->mode.vdisplay);<br>
> + regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00);<br>
> +<br>
> + /* Enable PLL */<br>
> + regmap_write(ctx->regmap, REG_RC_PLL_EN, REG_RC_PLL_EN_PLL_EN);<br>
> + usleep_range(3000, 4000);<br>
> + ret = regmap_read_poll_timeout(ctx->regmap, REG_RC_LVDS_PLL, pval,<br>
> + pval & REG_RC_LVDS_PLL_PLL_EN_STAT,<br>
> + 1000, 100000);<br>
> + if (ret) {<br>
> + dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);<br>
> + /* On failure, disable PLL again and exit. */<br>
> + regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);<br>
> + return;<br>
> + }<br>
> +<br>
> + /* Trigger reset after CSR register update. */<br>
> + regmap_write(ctx->regmap, REG_RC_RESET, REG_RC_RESET_SOFT_RESET);<br>
> +<br>
> + /* Clear all errors that got asserted during initialization. */<br>
> + regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);<br>
> + regmap_write(ctx->regmap, REG_IRQ_STAT, pval);<br>
> +}<br>
> +<br>
> +static void sn65dsi83_disable(struct drm_bridge *bridge)<br>
> +{<br>
> + struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);<br>
> +<br>
> + /* Clear reset, disable PLL */<br>
> + regmap_write(ctx->regmap, REG_RC_RESET, 0x00);<br>
> + regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);<br>
> +}<br>
> +<br>
> +static void sn65dsi83_post_disable(struct drm_bridge *bridge)<br>
> +{<br>
> + struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);<br>
> +<br>
> + /* Put the chip in reset, pull EN line low. */<br>
> + gpiod_set_value(ctx->enable_gpio, 0);<br>
> +}<br>
> +<br>
> +static enum drm_mode_status<br>
> +sn65dsi83_mode_valid(struct drm_bridge *bridge,<br>
> + const struct drm_display_info *info,<br>
> + const struct drm_display_mode *mode)<br>
> +{<br>
> + struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);<br>
> +<br>
> + /* LVDS output clock range 25..154 MHz */<br>
> + if (mode->clock < 25000)<br>
> + return MODE_CLOCK_LOW;<br>
> + if (mode->clock > 154000)<br>
> + return MODE_CLOCK_HIGH;<br>
> +<br>
> + switch (info->bus_formats[0]) {<br>
> + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:<br>
> + ctx->lvds_format_24bpp = false;<br>
> + ctx->lvds_format_jeida = false;<br>
> + break;<br>
> + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:<br>
> + ctx->lvds_format_24bpp = true;<br>
> + ctx->lvds_format_jeida = true;<br>
> + break;<br>
> + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:<br>
> + ctx->lvds_format_24bpp = true;<br>
> + ctx->lvds_format_jeida = false;<br>
> + break;<br>
> + default:<br>
> + ctx->lvds_format_24bpp = true;<br>
> + ctx->lvds_format_jeida = false;<br>
> + /*<br>
> + * Some bridges still don't set the correct LVDS bus pixel<br>
> + * format, use SPWG24 default format until those are fixed.<br>
> + */<br>
> + dev_warn(ctx->dev,<br>
> + "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n",<br>
> + info->bus_formats[0]);<br>
> + break;<br>
> + }<br>
> +<br>
> + return MODE_OK;<br>
> +}<br>
> +<br>
> +static void sn65dsi83_mode_set(struct drm_bridge *bridge,<br>
> + const struct drm_display_mode *mode,<br>
> + const struct drm_display_mode *adj)<br>
> +{<br>
> + struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);<br>
> + u32 input_bus_format = MEDIA_BUS_FMT_RGB888_1X24;<br>
> + struct drm_encoder *encoder = bridge->encoder;<br>
> + struct drm_device *ddev = encoder->dev;<br>
> + struct drm_connector *connector;<br>
> +<br>
> + /* The DSI format is always RGB888_1X24 */<br>
> + list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {<br>
> + if (connector->encoder != encoder)<br>
> + continue;<br>
> +<br>
> + drm_display_info_set_bus_formats(&connector->display_info,<br>
> + &input_bus_format, 1);<br>
> + }<br>
> +<br>
> + ctx->mode = *adj;<br>
> +}<br>
> +<br>
> +static const struct drm_bridge_funcs sn65dsi83_funcs = {<br>
> + .attach = sn65dsi83_attach,<br>
> + .pre_enable = sn65dsi83_pre_enable,<br>
> + .enable = sn65dsi83_enable,<br>
> + .disable = sn65dsi83_disable,<br>
> + .post_disable = sn65dsi83_post_disable,<br>
> + .mode_valid = sn65dsi83_mode_valid,<br>
> + .mode_set = sn65dsi83_mode_set,<br>
> +};<br>
> +<br>
> +static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)<br>
> +{<br>
> + struct drm_bridge *panel_bridge;<br>
> + struct device *dev = ctx->dev;<br>
> + struct device_node *endpoint;<br>
> + struct drm_panel *panel;<br>
> + int ret;<br>
> +<br>
> + endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);<br>
> + ctx->dsi_lanes = of_property_count_u32_elems(endpoint, "data-lanes");<br>
> + ctx->host_node = of_graph_get_remote_port_parent(endpoint);<br>
> + of_node_put(endpoint);<br>
> +<br>
> + if (ctx->dsi_lanes < 0 || ctx->dsi_lanes > 4)<br>
> + return -EINVAL;<br>
> + if (!ctx->host_node)<br>
> + return -ENODEV;<br>
> +<br>
> + ctx->lvds_dual_link = false;<br>
> + ctx->lvds_dual_link_even_odd_swap = false;<br>
> + if (model != MODEL_SN65DSI83) {<br>
> + struct device_node *port2, *port3;<br>
> + int dual_link;<br>
> +<br>
> + port2 = of_graph_get_port_by_id(dev->of_node, 2);<br>
> + port3 = of_graph_get_port_by_id(dev->of_node, 3);<br>
> + dual_link = drm_of_lvds_get_dual_link_pixel_order(port2, port3);<br>
> + of_node_put(port2);<br>
> + of_node_put(port3);<br>
> +<br>
> + if (dual_link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) {<br>
> + ctx->lvds_dual_link = true;<br>
> + /* Odd pixels to LVDS Channel A, even pixels to B */<br>
> + ctx->lvds_dual_link_even_odd_swap = false;<br>
> + } else if (dual_link == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {<br>
> + ctx->lvds_dual_link = true;<br>
> + /* Even pixels to LVDS Channel A, odd pixels to B */<br>
> + ctx->lvds_dual_link_even_odd_swap = true;<br>
> + }<br>
> + }<br>
> +<br>
> + ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_bridge);<br>
> + if (ret < 0)<br>
> + return ret;<br>
> + if (panel) {<br>
> + panel_bridge = devm_drm_panel_bridge_add(dev, panel);<br>
> + if (IS_ERR(panel_bridge))<br>
> + return PTR_ERR(panel_bridge);<br>
> + }<br>
> +<br>
> + ctx->panel_bridge = panel_bridge;<br>
> +<br>
> + return 0;<br>
> +}<br>
> +<br>
> +static int sn65dsi83_probe(struct i2c_client *client,<br>
> + const struct i2c_device_id *id)<br>
> +{<br>
> + struct device *dev = &client->dev;<br>
> + enum sn65dsi83_model model;<br>
> + struct sn65dsi83 *ctx;<br>
> + int ret;<br>
> +<br>
> + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);<br>
> + if (!ctx)<br>
> + return -ENOMEM;<br>
> +<br>
> + ctx->dev = dev;<br>
> +<br>
> + if (dev->of_node)<br>
> + model = (enum sn65dsi83_model)of_device_get_match_data(dev);<br>
> + else<br>
> + model = id->driver_data;<br>
> +<br>
> + ctx->enable_gpio = devm_gpiod_get(ctx->dev, "enable", GPIOD_OUT_LOW);<br>
> + if (IS_ERR(ctx->enable_gpio))<br>
> + return PTR_ERR(ctx->enable_gpio);<br>
> +<br>
> + ret = sn65dsi83_parse_dt(ctx, model);<br>
> + if (ret)<br>
> + return ret;<br>
> +<br>
> + ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config);<br>
> + if (IS_ERR(ctx->regmap))<br>
> + return PTR_ERR(ctx->regmap);<br>
> +<br>
> + dev_set_drvdata(dev, ctx);<br>
> + i2c_set_clientdata(client, ctx);<br>
> +<br>
> + ctx->bridge.funcs = &sn65dsi83_funcs;<br>
> + ctx->bridge.of_node = dev->of_node;<br>
> + drm_bridge_add(&ctx->bridge);<br>
> +<br>
> + return 0;<br>
> +}<br>
> +<br>
> +static int sn65dsi83_remove(struct i2c_client *client)<br>
> +{<br>
> + struct sn65dsi83 *ctx = i2c_get_clientdata(client);<br>
> +<br>
> + mipi_dsi_detach(ctx->dsi);<br>
> + mipi_dsi_device_unregister(ctx->dsi);<br>
> + drm_bridge_remove(&ctx->bridge);<br>
> + of_node_put(ctx->host_node);<br>
> +<br>
> + return 0;<br>
> +}<br>
> +<br>
> +static struct i2c_device_id sn65dsi83_id[] = {<br>
> + { "ti,sn65dsi83", MODEL_SN65DSI83 },<br>
> + { "ti,sn65dsi84", MODEL_SN65DSI84 },<br>
> + {},<br>
> +};<br>
> +MODULE_DEVICE_TABLE(i2c, sn65dsi83_id);<br>
> +<br>
> +static const struct of_device_id sn65dsi83_match_table[] = {<br>
> + { .compatible = "ti,sn65dsi83", .data = (void *)MODEL_SN65DSI83 },<br>
> + { .compatible = "ti,sn65dsi84", .data = (void *)MODEL_SN65DSI84 },<br>
> + {},<br>
> +};<br>
> +MODULE_DEVICE_TABLE(of, sn65dsi83_match_table);<br>
> +<br>
> +static struct i2c_driver sn65dsi83_driver = {<br>
> + .probe = sn65dsi83_probe,<br>
> + .remove = sn65dsi83_remove,<br>
> + .id_table = sn65dsi83_id,<br>
> + .driver = {<br>
> + .name = "sn65dsi83",<br>
> + .of_match_table = sn65dsi83_match_table,<br>
> + },<br>
> +};<br>
> +module_i2c_driver(sn65dsi83_driver);<br>
> +<br>
> +MODULE_AUTHOR("Marek Vasut <marex@denx.de>");<br>
> +MODULE_DESCRIPTION("TI SN65DSI83 DSI to LVDS bridge driver");<br>
> +MODULE_LICENSE("GPL v2");<br>
><br></p>
<p dir="ltr">------------------------------</p>
<p dir="ltr">Subject: Digest Footer</p>
<p dir="ltr">_______________________________________________<br>
dri-devel mailing list<br>
dri-devel@lists.freedesktop.org<br>
<a href="https://lists.freedesktop.org/mailman/listinfo/dri-devel">https://lists.freedesktop.org/mailman/listinfo/dri-devel</a><br></p>
<p dir="ltr">------------------------------</p>
<p dir="ltr">End of dri-devel Digest, Vol 134, Issue 221<br>
*******************************************<br>
</p>
</div>