diff options
author | Rob Clark <robdclark@chromium.org> | 2023-03-20 20:31:25 +0300 |
---|---|---|
committer | Rob Clark <robdclark@chromium.org> | 2023-03-20 20:31:25 +0300 |
commit | e752ab11dcb48353727ea26eefd740155e028865 (patch) | |
tree | bbd47198be4e42bbf990096ca36e96f3da40cfb6 /drivers/gpu/drm/bridge | |
parent | 1844e680d56bb0c4e0489138f2b7ba2dc1c988e3 (diff) | |
parent | 8bf6e20253b2d2b614f2c0b491f840e956fa6b05 (diff) | |
download | linux-e752ab11dcb48353727ea26eefd740155e028865.tar.xz |
Merge remote-tracking branch 'drm/drm-next' into msm-next
Merge drm-next into msm-next to pick up external clk and PM dependencies
for improved a6xx GPU reset sequence.
Signed-off-by: Rob Clark <robdclark@chromium.org>
Diffstat (limited to 'drivers/gpu/drm/bridge')
23 files changed, 438 insertions, 290 deletions
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 57946d80b02d..12e8f30c65f7 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -15,17 +15,6 @@ config DRM_PANEL_BRIDGE menu "Display Interface Bridges" depends on DRM && DRM_BRIDGE -config DRM_CDNS_DSI - tristate "Cadence DPI/DSI bridge" - select DRM_KMS_HELPER - select DRM_MIPI_DSI - select DRM_PANEL_BRIDGE - select GENERIC_PHY_MIPI_DPHY - depends on OF - help - Support Cadence DPI to DSI bridge. This is an internal - bridge and is meant to be directly embedded in a SoC. - config DRM_CHIPONE_ICN6211 tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge" depends on OF @@ -337,7 +326,7 @@ config DRM_TI_DLPC3433 input that produces a DMD output in RGB565, RGB666, RGB888 formats. - It supports upto 720p resolution with 60 and 120 Hz refresh + It supports up to 720p resolution with 60 and 120 Hz refresh rates. config DRM_TI_TFP410 diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 1884803c6860..52f6e8b4a821 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o obj-$(CONFIG_DRM_CHIPONE_ICN6211) += chipone-icn6211.o obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c index 339e0f05b260..3577c532abb4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c @@ -22,7 +22,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index b375887e655d..6846199a2ee1 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -26,7 +26,6 @@ #include <drm/display/drm_hdcp_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig index 1d06182bea71..ec35215a2003 100644 --- a/drivers/gpu/drm/bridge/cadence/Kconfig +++ b/drivers/gpu/drm/bridge/cadence/Kconfig @@ -1,4 +1,25 @@ # SPDX-License-Identifier: GPL-2.0-only +config DRM_CDNS_DSI + tristate "Cadence DPI/DSI bridge" + select DRM_KMS_HELPER + select DRM_MIPI_DSI + select DRM_PANEL_BRIDGE + select GENERIC_PHY_MIPI_DPHY + depends on OF + help + Support Cadence DPI to DSI bridge. This is an internal + bridge and is meant to be directly embedded in a SoC. + +if DRM_CDNS_DSI + +config DRM_CDNS_DSI_J721E + bool "J721E Cadence DSI wrapper support" + default y + help + Support J721E Cadence DSI wrapper. The wrapper manages + the routing of the DSS DPI signal to the Cadence DSI. +endif + config DRM_CDNS_MHDP8546 tristate "Cadence DPI/DP bridge" select DRM_DISPLAY_DP_HELPER diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile index 4d2db8df1bc6..c95fd5b81d13 100644 --- a/drivers/gpu/drm/bridge/cadence/Makefile +++ b/drivers/gpu/drm/bridge/cadence/Makefile @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o +cdns-dsi-y := cdns-dsi-core.o +cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c index 20bece84ff8c..5dbfc7226b31 100644 --- a/drivers/gpu/drm/bridge/cdns-dsi.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c @@ -6,10 +6,7 @@ */ #include <drm/drm_atomic_helper.h> -#include <drm/drm_bridge.h> #include <drm/drm_drv.h> -#include <drm/drm_mipi_dsi.h> -#include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> #include <video/mipi_display.h> @@ -18,14 +15,19 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/of_address.h> +#include <linux/of_device.h> #include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> -#include <linux/phy/phy.h> #include <linux/phy/phy-mipi-dphy.h> +#include "cdns-dsi-core.h" +#ifdef CONFIG_DRM_CDNS_DSI_J721E +#include "cdns-dsi-j721e.h" +#endif + #define IP_CONF 0x0 #define SP_HS_FIFO_DEPTH(x) (((x) & GENMASK(30, 26)) >> 26) #define SP_LP_FIFO_DEPTH(x) (((x) & GENMASK(25, 21)) >> 21) @@ -424,48 +426,6 @@ #define DSI_NULL_FRAME_OVERHEAD 6 #define DSI_EOT_PKT_SIZE 4 -struct cdns_dsi_output { - struct mipi_dsi_device *dev; - struct drm_panel *panel; - struct drm_bridge *bridge; - union phy_configure_opts phy_opts; -}; - -enum cdns_dsi_input_id { - CDNS_SDI_INPUT, - CDNS_DPI_INPUT, - CDNS_DSC_INPUT, -}; - -struct cdns_dsi_cfg { - unsigned int hfp; - unsigned int hsa; - unsigned int hbp; - unsigned int hact; - unsigned int htotal; -}; - -struct cdns_dsi_input { - enum cdns_dsi_input_id id; - struct drm_bridge bridge; -}; - -struct cdns_dsi { - struct mipi_dsi_host base; - void __iomem *regs; - struct cdns_dsi_input input; - struct cdns_dsi_output output; - unsigned int direct_cmd_fifo_depth; - unsigned int rx_fifo_depth; - struct completion direct_cmd_comp; - struct clk *dsi_p_clk; - struct reset_control *dsi_p_rst; - struct clk *dsi_sys_clk; - bool link_initialized; - bool phy_initialized; - struct phy *dphy; -}; - static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input) { return container_of(input, struct cdns_dsi, input); @@ -709,6 +669,10 @@ static void cdns_dsi_bridge_disable(struct drm_bridge *bridge) val = readl(dsi->regs + MCTL_MAIN_EN) & ~IF_EN(input->id); writel(val, dsi->regs + MCTL_MAIN_EN); + + if (dsi->platform_ops && dsi->platform_ops->disable) + dsi->platform_ops->disable(dsi); + pm_runtime_put(dsi->base.dev); } @@ -804,6 +768,9 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge) if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0)) return; + if (dsi->platform_ops && dsi->platform_ops->enable) + dsi->platform_ops->enable(dsi); + mode = &bridge->encoder->crtc->state->adjusted_mode; nlanes = output->dev->lanes; @@ -1244,6 +1211,8 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev) goto err_disable_pclk; } + dsi->platform_ops = of_device_get_match_data(&pdev->dev); + val = readl(dsi->regs + IP_CONF); dsi->direct_cmd_fifo_depth = 1 << (DIRCMD_FIFO_DEPTH(val) + 2); dsi->rx_fifo_depth = RX_FIFO_DEPTH(val); @@ -1279,14 +1248,27 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev) dsi->base.dev = &pdev->dev; dsi->base.ops = &cdns_dsi_ops; + if (dsi->platform_ops && dsi->platform_ops->init) { + ret = dsi->platform_ops->init(dsi); + if (ret != 0) { + dev_err(&pdev->dev, "platform initialization failed: %d\n", + ret); + goto err_disable_runtime_pm; + } + } + ret = mipi_dsi_host_register(&dsi->base); if (ret) - goto err_disable_runtime_pm; + goto err_deinit_platform; clk_disable_unprepare(dsi->dsi_p_clk); return 0; +err_deinit_platform: + if (dsi->platform_ops && dsi->platform_ops->deinit) + dsi->platform_ops->deinit(dsi); + err_disable_runtime_pm: pm_runtime_disable(&pdev->dev); @@ -1301,6 +1283,10 @@ static int cdns_dsi_drm_remove(struct platform_device *pdev) struct cdns_dsi *dsi = platform_get_drvdata(pdev); mipi_dsi_host_unregister(&dsi->base); + + if (dsi->platform_ops && dsi->platform_ops->deinit) + dsi->platform_ops->deinit(dsi); + pm_runtime_disable(&pdev->dev); return 0; @@ -1308,6 +1294,9 @@ static int cdns_dsi_drm_remove(struct platform_device *pdev) static const struct of_device_id cdns_dsi_of_match[] = { { .compatible = "cdns,dsi" }, +#ifdef CONFIG_DRM_CDNS_DSI_J721E + { .compatible = "ti,j721e-dsi", .data = &dsi_ti_j721e_ops, }, +#endif { }, }; MODULE_DEVICE_TABLE(of, cdns_dsi_of_match); diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h new file mode 100644 index 000000000000..ca7ea2da635c --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright: 2017 Cadence Design Systems, Inc. + * + * Author: Boris Brezillon <boris.brezillon@bootlin.com> + */ + +#ifndef __CDNS_DSI_H__ +#define __CDNS_DSI_H__ + +#include <drm/drm_bridge.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> + +#include <linux/bits.h> +#include <linux/completion.h> +#include <linux/phy/phy.h> + +struct clk; +struct reset_control; + +struct cdns_dsi_output { + struct mipi_dsi_device *dev; + struct drm_panel *panel; + struct drm_bridge *bridge; + union phy_configure_opts phy_opts; +}; + +enum cdns_dsi_input_id { + CDNS_SDI_INPUT, + CDNS_DPI_INPUT, + CDNS_DSC_INPUT, +}; + +struct cdns_dsi_cfg { + unsigned int hfp; + unsigned int hsa; + unsigned int hbp; + unsigned int hact; + unsigned int htotal; +}; + +struct cdns_dsi_input { + enum cdns_dsi_input_id id; + struct drm_bridge bridge; +}; + +struct cdns_dsi; + +/** + * struct cdns_dsi_platform_ops - CDNS DSI Platform operations + * @init: Called in the CDNS DSI probe + * @deinit: Called in the CDNS DSI remove + * @enable: Called at the beginning of CDNS DSI bridge enable + * @disable: Called at the end of CDNS DSI bridge disable + */ +struct cdns_dsi_platform_ops { + int (*init)(struct cdns_dsi *dsi); + void (*deinit)(struct cdns_dsi *dsi); + void (*enable)(struct cdns_dsi *dsi); + void (*disable)(struct cdns_dsi *dsi); +}; + +struct cdns_dsi { + struct mipi_dsi_host base; + void __iomem *regs; +#ifdef CONFIG_DRM_CDNS_DSI_J721E + void __iomem *j721e_regs; +#endif + const struct cdns_dsi_platform_ops *platform_ops; + struct cdns_dsi_input input; + struct cdns_dsi_output output; + unsigned int direct_cmd_fifo_depth; + unsigned int rx_fifo_depth; + struct completion direct_cmd_comp; + struct clk *dsi_p_clk; + struct reset_control *dsi_p_rst; + struct clk *dsi_sys_clk; + bool link_initialized; + bool phy_initialized; + struct phy *dphy; +}; + +#endif /* !__CDNS_DSI_H__ */ diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.c new file mode 100644 index 000000000000..b654d4b3cb5c --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TI j721e Cadence DSI wrapper + * + * Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Rahul T R <r-ravikumar@ti.com> + */ + +#include <linux/io.h> +#include <linux/platform_device.h> + +#include "cdns-dsi-j721e.h" + +#define DSI_WRAP_REVISION 0x0 +#define DSI_WRAP_DPI_CONTROL 0x4 +#define DSI_WRAP_DSC_CONTROL 0x8 +#define DSI_WRAP_DPI_SECURE 0xc +#define DSI_WRAP_DSI_0_ASF_STATUS 0x10 + +#define DSI_WRAP_DPI_0_EN BIT(0) +#define DSI_WRAP_DSI2_MUX_SEL BIT(4) + +static int cdns_dsi_j721e_init(struct cdns_dsi *dsi) +{ + struct platform_device *pdev = to_platform_device(dsi->base.dev); + + dsi->j721e_regs = devm_platform_ioremap_resource(pdev, 1); + return PTR_ERR_OR_ZERO(dsi->j721e_regs); +} + +static void cdns_dsi_j721e_enable(struct cdns_dsi *dsi) +{ + /* + * Enable DPI0 as its input. DSS0 DPI2 is connected + * to DSI DPI0. This is the only supported configuration on + * J721E. + */ + writel(DSI_WRAP_DPI_0_EN, dsi->j721e_regs + DSI_WRAP_DPI_CONTROL); +} + +static void cdns_dsi_j721e_disable(struct cdns_dsi *dsi) +{ + /* Put everything to defaults */ + writel(0, dsi->j721e_regs + DSI_WRAP_DPI_CONTROL); +} + +const struct cdns_dsi_platform_ops dsi_ti_j721e_ops = { + .init = cdns_dsi_j721e_init, + .enable = cdns_dsi_j721e_enable, + .disable = cdns_dsi_j721e_disable, +}; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.h b/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.h new file mode 100644 index 000000000000..275e5e8e7583 --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * TI j721e Cadence DSI wrapper + * + * Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Rahul T R <r-ravikumar@ti.com> + */ + +#ifndef __CDNS_DSI_J721E_H__ +#define __CDNS_DSI_J721E_H__ + +#include "cdns-dsi-core.h" + +extern const struct cdns_dsi_platform_ops dsi_ti_j721e_ops; + +#endif /* !__CDNS_DSI_J721E_H__ */ diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 31442a922502..f6822dfa3805 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -43,7 +43,6 @@ #include <drm/drm_atomic_state_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_connector.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c index f9e0f8d99268..6bac160b395b 100644 --- a/drivers/gpu/drm/bridge/fsl-ldb.c +++ b/drivers/gpu/drm/bridge/fsl-ldb.c @@ -18,7 +18,6 @@ #include <drm/drm_of.h> #include <drm/drm_panel.h> -#define LDB_CTRL 0x5c #define LDB_CTRL_CH0_ENABLE BIT(0) #define LDB_CTRL_CH0_DI_SELECT BIT(1) #define LDB_CTRL_CH1_ENABLE BIT(2) @@ -35,9 +34,13 @@ #define LDB_CTRL_ASYNC_FIFO_ENABLE BIT(24) #define LDB_CTRL_ASYNC_FIFO_THRESHOLD_MASK GENMASK(27, 25) -#define LVDS_CTRL 0x128 #define LVDS_CTRL_CH0_EN BIT(0) #define LVDS_CTRL_CH1_EN BIT(1) +/* + * LVDS_CTRL_LVDS_EN bit is poorly named in i.MX93 reference manual. + * Clear it to enable LVDS and set it to disable LVDS. + */ +#define LVDS_CTRL_LVDS_EN BIT(1) #define LVDS_CTRL_VBG_EN BIT(2) #define LVDS_CTRL_HS_EN BIT(3) #define LVDS_CTRL_PRE_EMPH_EN BIT(4) @@ -52,6 +55,29 @@ #define LVDS_CTRL_VBG_ADJ(n) (((n) & 0x7) << 17) #define LVDS_CTRL_VBG_ADJ_MASK GENMASK(19, 17) +enum fsl_ldb_devtype { + IMX8MP_LDB, + IMX93_LDB, +}; + +struct fsl_ldb_devdata { + u32 ldb_ctrl; + u32 lvds_ctrl; + bool lvds_en_bit; +}; + +static const struct fsl_ldb_devdata fsl_ldb_devdata[] = { + [IMX8MP_LDB] = { + .ldb_ctrl = 0x5c, + .lvds_ctrl = 0x128, + }, + [IMX93_LDB] = { + .ldb_ctrl = 0x20, + .lvds_ctrl = 0x24, + .lvds_en_bit = true, + }, +}; + struct fsl_ldb { struct device *dev; struct drm_bridge bridge; @@ -59,6 +85,7 @@ struct fsl_ldb { struct clk *clk; struct regmap *regmap; bool lvds_dual_link; + const struct fsl_ldb_devdata *devdata; }; static inline struct fsl_ldb *to_fsl_ldb(struct drm_bridge *bridge) @@ -66,6 +93,14 @@ static inline struct fsl_ldb *to_fsl_ldb(struct drm_bridge *bridge) return container_of(bridge, struct fsl_ldb, bridge); } +static unsigned long fsl_ldb_link_frequency(struct fsl_ldb *fsl_ldb, int clock) +{ + if (fsl_ldb->lvds_dual_link) + return clock * 3500; + else + return clock * 7000; +} + static int fsl_ldb_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { @@ -85,6 +120,8 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge, const struct drm_display_mode *mode; struct drm_connector *connector; struct drm_crtc *crtc; + unsigned long configured_link_freq; + unsigned long requested_link_freq; bool lvds_format_24bpp; bool lvds_format_jeida; u32 reg; @@ -128,10 +165,15 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge, crtc_state = drm_atomic_get_new_crtc_state(state, crtc); mode = &crtc_state->adjusted_mode; - if (fsl_ldb->lvds_dual_link) - clk_set_rate(fsl_ldb->clk, mode->clock * 3500); - else - clk_set_rate(fsl_ldb->clk, mode->clock * 7000); + requested_link_freq = fsl_ldb_link_frequency(fsl_ldb, mode->clock); + clk_set_rate(fsl_ldb->clk, requested_link_freq); + + configured_link_freq = clk_get_rate(fsl_ldb->clk); + if (configured_link_freq != requested_link_freq) + dev_warn(fsl_ldb->dev, "Configured LDB clock (%lu Hz) does not match requested LVDS clock: %lu Hz", + configured_link_freq, + requested_link_freq); + clk_prepare_enable(fsl_ldb->clk); /* Program LDB_CTRL */ @@ -158,12 +200,12 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge, reg |= LDB_CTRL_DI1_VSYNC_POLARITY; } - regmap_write(fsl_ldb->regmap, LDB_CTRL, reg); + regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->ldb_ctrl, reg); /* Program LVDS_CTRL */ reg = LVDS_CTRL_CC_ADJ(2) | LVDS_CTRL_PRE_EMPH_EN | LVDS_CTRL_PRE_EMPH_ADJ(3) | LVDS_CTRL_VBG_EN; - regmap_write(fsl_ldb->regmap, LVDS_CTRL, reg); + regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, reg); /* Wait for VBG to stabilize. */ usleep_range(15, 20); @@ -172,7 +214,7 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge, if (fsl_ldb->lvds_dual_link) reg |= LVDS_CTRL_CH1_EN; - regmap_write(fsl_ldb->regmap, LVDS_CTRL, reg); + regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, reg); } static void fsl_ldb_atomic_disable(struct drm_bridge *bridge, @@ -180,9 +222,14 @@ static void fsl_ldb_atomic_disable(struct drm_bridge *bridge, { struct fsl_ldb *fsl_ldb = to_fsl_ldb(bridge); - /* Stop both channels. */ - regmap_write(fsl_ldb->regmap, LVDS_CTRL, 0); - regmap_write(fsl_ldb->regmap, LDB_CTRL, 0); + /* Stop channel(s). */ + if (fsl_ldb->devdata->lvds_en_bit) + /* Set LVDS_CTRL_LVDS_EN bit to disable. */ + regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, + LVDS_CTRL_LVDS_EN); + else + regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, 0); + regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->ldb_ctrl, 0); clk_disable_unprepare(fsl_ldb->clk); } @@ -248,6 +295,10 @@ static int fsl_ldb_probe(struct platform_device *pdev) if (!fsl_ldb) return -ENOMEM; + fsl_ldb->devdata = of_device_get_match_data(dev); + if (!fsl_ldb->devdata) + return -EINVAL; + fsl_ldb->dev = &pdev->dev; fsl_ldb->bridge.funcs = &funcs; fsl_ldb->bridge.of_node = dev->of_node; @@ -306,7 +357,10 @@ static int fsl_ldb_remove(struct platform_device *pdev) } static const struct of_device_id fsl_ldb_match[] = { - { .compatible = "fsl,imx8mp-ldb", }, + { .compatible = "fsl,imx8mp-ldb", + .data = &fsl_ldb_devdata[IMX8MP_LDB], }, + { .compatible = "fsl,imx93-ldb", + .data = &fsl_ldb_devdata[IMX93_LDB], }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, fsl_ldb_match); diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 9cda2df21b88..bc451b2a77c2 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -26,7 +26,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index b34860871627..a2d723d6a4be 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -22,7 +22,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> #include <drm/drm_modes.h> #include <drm/drm_print.h> diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index 3ce4e495aee5..a25d21a7d5c1 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -19,6 +19,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_mipi_dsi.h> +#include <drm/drm_of.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> @@ -33,7 +34,7 @@ struct lt9611 { struct device *dev; struct drm_bridge bridge; - struct drm_connector connector; + struct drm_bridge *next_bridge; struct regmap *regmap; @@ -58,7 +59,6 @@ struct lt9611 { enum drm_connector_status status; u8 edid_buf[EDID_SEG_SIZE]; - u32 vic; }; #define LT9611_PAGE_CONTROL 0xff @@ -84,34 +84,11 @@ static const struct regmap_config lt9611_regmap_config = { .num_ranges = ARRAY_SIZE(lt9611_ranges), }; -struct lt9611_mode { - u16 hdisplay; - u16 vdisplay; - u8 vrefresh; - u8 lanes; - u8 intfs; -}; - -static struct lt9611_mode lt9611_modes[] = { - { 3840, 2160, 30, 4, 2 }, /* 3840x2160 24bit 30Hz 4Lane 2ports */ - { 1920, 1080, 60, 4, 1 }, /* 1080P 24bit 60Hz 4lane 1port */ - { 1920, 1080, 30, 3, 1 }, /* 1080P 24bit 30Hz 3lane 1port */ - { 1920, 1080, 24, 3, 1 }, - { 720, 480, 60, 4, 1 }, - { 720, 576, 50, 2, 1 }, - { 640, 480, 60, 2, 1 }, -}; - static struct lt9611 *bridge_to_lt9611(struct drm_bridge *bridge) { return container_of(bridge, struct lt9611, bridge); } -static struct lt9611 *connector_to_lt9611(struct drm_connector *connector) -{ - return container_of(connector, struct lt9611, connector); -} - static int lt9611_mipi_input_analog(struct lt9611 *lt9611) { const struct reg_sequence reg_cfg[] = { @@ -141,7 +118,7 @@ static int lt9611_mipi_input_digital(struct lt9611 *lt9611, { 0x8306, 0x0a }, }; - if (mode->hdisplay == 3840) + if (lt9611->dsi1_node) reg_cfg[1].def = 0x03; return regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); @@ -159,12 +136,12 @@ static void lt9611_mipi_video_setup(struct lt9611 *lt9611, hactive = mode->hdisplay; hsync_len = mode->hsync_end - mode->hsync_start; hfront_porch = mode->hsync_start - mode->hdisplay; - hsync_porch = hsync_len + mode->htotal - mode->hsync_end; + hsync_porch = mode->htotal - mode->hsync_start; vactive = mode->vdisplay; vsync_len = mode->vsync_end - mode->vsync_start; vfront_porch = mode->vsync_start - mode->vdisplay; - vsync_porch = vsync_len + mode->vtotal - mode->vsync_end; + vsync_porch = mode->vtotal - mode->vsync_start; regmap_write(lt9611->regmap, 0x830d, (u8)(v_total / 256)); regmap_write(lt9611->regmap, 0x830e, (u8)(v_total % 256)); @@ -187,12 +164,14 @@ static void lt9611_mipi_video_setup(struct lt9611 *lt9611, regmap_write(lt9611->regmap, 0x8319, (u8)(hfront_porch % 256)); - regmap_write(lt9611->regmap, 0x831a, (u8)(hsync_porch / 256)); + regmap_write(lt9611->regmap, 0x831a, (u8)(hsync_porch / 256) | + ((hfront_porch / 256) << 4)); regmap_write(lt9611->regmap, 0x831b, (u8)(hsync_porch % 256)); } -static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode) +static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode, unsigned int postdiv) { + unsigned int pcr_m = mode->clock * 5 * postdiv / 27000; const struct reg_sequence reg_cfg[] = { { 0x830b, 0x01 }, { 0x830c, 0x10 }, @@ -207,45 +186,40 @@ static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mod /* stage 2 */ { 0x834a, 0x40 }, - { 0x831d, 0x10 }, /* MK limit */ { 0x832d, 0x38 }, { 0x8331, 0x08 }, }; - const struct reg_sequence reg_cfg2[] = { - { 0x830b, 0x03 }, - { 0x830c, 0xd0 }, - { 0x8348, 0x03 }, - { 0x8349, 0xe0 }, - { 0x8324, 0x72 }, - { 0x8325, 0x00 }, - { 0x832a, 0x01 }, - { 0x834a, 0x10 }, - { 0x831d, 0x10 }, - { 0x8326, 0x37 }, - }; + u8 pol = 0x10; - regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + pol |= 0x2; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + pol |= 0x1; + regmap_write(lt9611->regmap, 0x831d, pol); - switch (mode->hdisplay) { - case 640: - regmap_write(lt9611->regmap, 0x8326, 0x14); - break; - case 1920: - regmap_write(lt9611->regmap, 0x8326, 0x37); - break; - case 3840: - regmap_multi_reg_write(lt9611->regmap, reg_cfg2, ARRAY_SIZE(reg_cfg2)); - break; + regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); + if (lt9611->dsi1_node) { + unsigned int hact = mode->hdisplay; + + hact >>= 2; + hact += 0x50; + hact = min(hact, 0x3e0U); + regmap_write(lt9611->regmap, 0x830b, hact / 256); + regmap_write(lt9611->regmap, 0x830c, hact % 256); + regmap_write(lt9611->regmap, 0x8348, hact / 256); + regmap_write(lt9611->regmap, 0x8349, hact % 256); } + regmap_write(lt9611->regmap, 0x8326, pcr_m); + /* pcr rst */ regmap_write(lt9611->regmap, 0x8011, 0x5a); regmap_write(lt9611->regmap, 0x8011, 0xfa); } -static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode) +static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode, unsigned int *postdiv) { unsigned int pclk = mode->clock; const struct reg_sequence reg_cfg[] = { @@ -264,12 +238,16 @@ static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); - if (pclk > 150000) + if (pclk > 150000) { regmap_write(lt9611->regmap, 0x812d, 0x88); - else if (pclk > 70000) + *postdiv = 1; + } else if (pclk > 70000) { regmap_write(lt9611->regmap, 0x812d, 0x99); - else + *postdiv = 2; + } else { regmap_write(lt9611->regmap, 0x812d, 0xaa); + *postdiv = 4; + } /* * first divide pclk by 2 first @@ -354,13 +332,55 @@ end: return temp; } -static void lt9611_hdmi_tx_digital(struct lt9611 *lt9611) +static void lt9611_hdmi_set_infoframes(struct lt9611 *lt9611, + struct drm_connector *connector, + struct drm_display_mode *mode) { - regmap_write(lt9611->regmap, 0x8443, 0x46 - lt9611->vic); - regmap_write(lt9611->regmap, 0x8447, lt9611->vic); - regmap_write(lt9611->regmap, 0x843d, 0x0a); /* UD1 infoframe */ + union hdmi_infoframe infoframe; + ssize_t len; + u8 iframes = 0x0a; /* UD1 infoframe */ + u8 buf[32]; + int ret; + int i; - regmap_write(lt9611->regmap, 0x82d6, 0x8c); + ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe.avi, + connector, + mode); + if (ret < 0) + goto out; + + len = hdmi_infoframe_pack(&infoframe, buf, sizeof(buf)); + if (len < 0) + goto out; + + for (i = 0; i < len; i++) + regmap_write(lt9611->regmap, 0x8440 + i, buf[i]); + + ret = drm_hdmi_vendor_infoframe_from_display_mode(&infoframe.vendor.hdmi, + connector, + mode); + if (ret < 0) + goto out; + + len = hdmi_infoframe_pack(&infoframe, buf, sizeof(buf)); + if (len < 0) + goto out; + + for (i = 0; i < len; i++) + regmap_write(lt9611->regmap, 0x8474 + i, buf[i]); + + iframes |= 0x20; + +out: + regmap_write(lt9611->regmap, 0x843d, iframes); /* UD1 infoframe */ +} + +static void lt9611_hdmi_tx_digital(struct lt9611 *lt9611, bool is_hdmi) +{ + if (is_hdmi) + regmap_write(lt9611->regmap, 0x82d6, 0x8c); + else + regmap_write(lt9611->regmap, 0x82d6, 0x0c); regmap_write(lt9611->regmap, 0x82d7, 0x04); } @@ -449,12 +469,11 @@ static void lt9611_sleep_setup(struct lt9611 *lt9611) { 0x8023, 0x01 }, { 0x8157, 0x03 }, /* set addr pin as output */ { 0x8149, 0x0b }, - { 0x8151, 0x30 }, /* disable IRQ */ + { 0x8102, 0x48 }, /* MIPI Rx power down */ { 0x8123, 0x80 }, { 0x8130, 0x00 }, - { 0x8100, 0x01 }, /* bandgap power down */ - { 0x8101, 0x00 }, /* system clk power down */ + { 0x8011, 0x0a }, }; regmap_multi_reg_write(lt9611->regmap, @@ -565,24 +584,9 @@ static int lt9611_regulator_enable(struct lt9611 *lt9611) return 0; } -static struct lt9611_mode *lt9611_find_mode(const struct drm_display_mode *mode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(lt9611_modes); i++) { - if (lt9611_modes[i].hdisplay == mode->hdisplay && - lt9611_modes[i].vdisplay == mode->vdisplay && - lt9611_modes[i].vrefresh == drm_mode_vrefresh(mode)) { - return <9611_modes[i]; - } - } - - return NULL; -} - -/* connector funcs */ -static enum drm_connector_status __lt9611_detect(struct lt9611 *lt9611) +static enum drm_connector_status lt9611_bridge_detect(struct drm_bridge *bridge) { + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); unsigned int reg_val = 0; int connected = 0; @@ -595,12 +599,6 @@ static enum drm_connector_status __lt9611_detect(struct lt9611 *lt9611) return lt9611->status; } -static enum drm_connector_status -lt9611_connector_detect(struct drm_connector *connector, bool force) -{ - return __lt9611_detect(connector_to_lt9611(connector)); -} - static int lt9611_read_edid(struct lt9611 *lt9611) { unsigned int temp; @@ -682,36 +680,37 @@ lt9611_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) return 0; } -static int lt9611_connector_get_modes(struct drm_connector *connector) -{ - struct lt9611 *lt9611 = connector_to_lt9611(connector); - unsigned int count; - struct edid *edid; - - lt9611_power_on(lt9611); - edid = drm_do_get_edid(connector, lt9611_get_edid_block, lt9611); - drm_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); - kfree(edid); - - return count; -} - -static enum drm_mode_status -lt9611_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct lt9611_mode *lt9611_mode = lt9611_find_mode(mode); - - return lt9611_mode ? MODE_OK : MODE_BAD; -} - /* bridge funcs */ static void lt9611_bridge_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + struct drm_atomic_state *state = old_bridge_state->base.state; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *mode; + unsigned int postdiv; + + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (WARN_ON(!connector)) + return; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + + mode = &crtc_state->adjusted_mode; + + lt9611_mipi_input_digital(lt9611, mode); + lt9611_pll_setup(lt9611, mode, &postdiv); + lt9611_mipi_video_setup(lt9611, mode); + lt9611_pcr_setup(lt9611, mode, postdiv); if (lt9611_power_on(lt9611)) { dev_err(lt9611->dev, "power on failed\n"); @@ -719,7 +718,8 @@ lt9611_bridge_atomic_enable(struct drm_bridge *bridge, } lt9611_mipi_input_analog(lt9611); - lt9611_hdmi_tx_digital(lt9611); + lt9611_hdmi_set_infoframes(lt9611, connector, mode); + lt9611_hdmi_tx_digital(lt9611, connector->display_info.is_hdmi); lt9611_hdmi_tx_phy(lt9611); msleep(500); @@ -750,25 +750,10 @@ lt9611_bridge_atomic_disable(struct drm_bridge *bridge, } } -static struct -drm_connector_helper_funcs lt9611_bridge_connector_helper_funcs = { - .get_modes = lt9611_connector_get_modes, - .mode_valid = lt9611_connector_mode_valid, -}; - -static const struct drm_connector_funcs lt9611_bridge_connector_funcs = { - .fill_modes = drm_helper_probe_single_connector_modes, - .detect = lt9611_connector_detect, - .destroy = drm_connector_cleanup, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611, struct device_node *dsi_node) { - const struct mipi_dsi_device_info info = { "lt9611", 0, NULL }; + const struct mipi_dsi_device_info info = { "lt9611", 0, lt9611->dev->of_node}; struct mipi_dsi_device *dsi; struct mipi_dsi_host *host; struct device *dev = lt9611->dev; @@ -800,70 +785,54 @@ static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611, return dsi; } -static int lt9611_connector_init(struct drm_bridge *bridge, struct lt9611 *lt9611) -{ - int ret; - - ret = drm_connector_init(bridge->dev, <9611->connector, - <9611_bridge_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA); - if (ret) { - DRM_ERROR("Failed to initialize connector with drm\n"); - return ret; - } - - drm_connector_helper_add(<9611->connector, - <9611_bridge_connector_helper_funcs); - - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - - drm_connector_attach_encoder(<9611->connector, bridge->encoder); - - return 0; -} - static int lt9611_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct lt9611 *lt9611 = bridge_to_lt9611(bridge); - int ret; - if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { - ret = lt9611_connector_init(bridge, lt9611); - if (ret < 0) - return ret; - } - - return 0; + return drm_bridge_attach(bridge->encoder, lt9611->next_bridge, + bridge, flags); } static enum drm_mode_status lt9611_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode) { - struct lt9611_mode *lt9611_mode = lt9611_find_mode(mode); struct lt9611 *lt9611 = bridge_to_lt9611(bridge); - if (!lt9611_mode) - return MODE_BAD; - else if (lt9611_mode->intfs > 1 && !lt9611->dsi1) + if (mode->hdisplay > 3840) + return MODE_BAD_HVALUE; + + if (mode->vdisplay > 2160) + return MODE_BAD_VVALUE; + + if (mode->hdisplay == 3840 && + mode->vdisplay == 2160 && + drm_mode_vrefresh(mode) > 30) + return MODE_CLOCK_HIGH; + + if (mode->hdisplay > 2000 && !lt9611->dsi1_node) return MODE_PANEL; else return MODE_OK; } -static void lt9611_bridge_pre_enable(struct drm_bridge *bridge) +static void lt9611_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + static const struct reg_sequence reg_cfg[] = { + { 0x8102, 0x12 }, + { 0x8123, 0x40 }, + { 0x8130, 0xea }, + { 0x8011, 0xfa }, + }; if (!lt9611->sleep) return; - lt9611_reset(lt9611); - regmap_write(lt9611->regmap, 0x80ee, 0x01); + regmap_multi_reg_write(lt9611->regmap, + reg_cfg, ARRAY_SIZE(reg_cfg)); lt9611->sleep = false; } @@ -877,33 +846,6 @@ lt9611_bridge_atomic_post_disable(struct drm_bridge *bridge, lt9611_sleep_setup(lt9611); } -static void lt9611_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adj_mode) -{ - struct lt9611 *lt9611 = bridge_to_lt9611(bridge); - struct hdmi_avi_infoframe avi_frame; - int ret; - - lt9611_bridge_pre_enable(bridge); - - lt9611_mipi_input_digital(lt9611, mode); - lt9611_pll_setup(lt9611, mode); - lt9611_mipi_video_setup(lt9611, mode); - lt9611_pcr_setup(lt9611, mode); - - ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame, - <9611->connector, - mode); - if (!ret) - lt9611->vic = avi_frame.video_code; -} - -static enum drm_connector_status lt9611_bridge_detect(struct drm_bridge *bridge) -{ - return __lt9611_detect(bridge_to_lt9611(bridge)); -} - static struct edid *lt9611_bridge_get_edid(struct drm_bridge *bridge, struct drm_connector *connector) { @@ -949,11 +891,11 @@ lt9611_atomic_get_input_bus_fmts(struct drm_bridge *bridge, static const struct drm_bridge_funcs lt9611_bridge_funcs = { .attach = lt9611_bridge_attach, .mode_valid = lt9611_bridge_mode_valid, - .mode_set = lt9611_bridge_mode_set, .detect = lt9611_bridge_detect, .get_edid = lt9611_bridge_get_edid, .hpd_enable = lt9611_bridge_hpd_enable, + .atomic_pre_enable = lt9611_bridge_atomic_pre_enable, .atomic_enable = lt9611_bridge_atomic_enable, .atomic_disable = lt9611_bridge_atomic_disable, .atomic_post_disable = lt9611_bridge_atomic_post_disable, @@ -976,7 +918,7 @@ static int lt9611_parse_dt(struct device *dev, lt9611->ac_mode = of_property_read_bool(dev->of_node, "lt,ac-mode"); - return 0; + return drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611->next_bridge); } static int lt9611_gpio_init(struct lt9611 *lt9611) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index c58f7bb6fca6..9316384b4474 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -81,6 +81,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge, return ret; } + drm_panel_bridge_set_orientation(connector, bridge); + drm_connector_attach_encoder(&panel_bridge->connector, bridge->encoder); @@ -409,15 +411,16 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev, return ERR_PTR(-ENOMEM); bridge = drm_panel_bridge_add_typed(panel, connector_type); - if (!IS_ERR(bridge)) { - *ptr = bridge; - devres_add(dev, ptr); - } else { + if (IS_ERR(bridge)) { devres_free(ptr); + return bridge; } bridge->pre_enable_prev_first = panel->prepare_prev_first; + *ptr = bridge; + devres_add(dev, ptr); + return bridge; } EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed); diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index d212ff7f7a87..ef66461e7f7c 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -239,12 +239,12 @@ static void sii902x_reset(struct sii902x *sii902x) if (!sii902x->reset_gpio) return; - gpiod_set_value(sii902x->reset_gpio, 1); + gpiod_set_value_cansleep(sii902x->reset_gpio, 1); /* The datasheet says treset-min = 100us. Make it 150us to be sure. */ usleep_range(150, 200); - gpiod_set_value(sii902x->reset_gpio, 0); + gpiod_set_value_cansleep(sii902x->reset_gpio, 0); } static enum drm_connector_status sii902x_detect(struct sii902x *sii902x) @@ -1116,7 +1116,8 @@ static int sii902x_probe(struct i2c_client *client) sii902x->next_bridge = of_drm_find_bridge(remote); of_node_put(remote); if (!sii902x->next_bridge) - return -EPROBE_DEFER; + return dev_err_probe(dev, -EPROBE_DEFER, + "Failed to find remote bridge\n"); } mutex_init(&sii902x->mutex); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index a2f0860b20bb..d751820c6da6 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -193,6 +193,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) struct hdmi_codec_pdata pdata; struct platform_device *platform; + memset(&pdata, 0, sizeof(pdata)); pdata.ops = &dw_hdmi_i2s_ops; pdata.i2s = 1; pdata.max_i2s_channels = 8; diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index 0b6a28436885..77f7f7f54757 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -229,6 +229,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) ctx->bridge.funcs = &tc358762_bridge_funcs; ctx->bridge.type = DRM_MODE_CONNECTOR_DPI; ctx->bridge.of_node = dev->of_node; + ctx->bridge.pre_enable_prev_first = true; drm_bridge_add(&ctx->bridge); diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index 53259c12d777..f85654f1b104 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -369,6 +369,7 @@ static int tc358764_probe(struct mipi_dsi_device *dsi) ctx->bridge.funcs = &tc358764_bridge_funcs; ctx->bridge.of_node = dev->of_node; + ctx->bridge.pre_enable_prev_first = true; drm_bridge_add(&ctx->bridge); diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index a4725efe812d..6d16ec45ea61 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1264,10 +1264,10 @@ static int tc_dsi_rx_enable(struct tc_data *tc) u32 value; int ret; - regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 5); - regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 5); - regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 5); - regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 5); + regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 25); + regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 25); + regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 25); + regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 25); regmap_write(tc->regmap, PPI_D0S_ATMR, 0); regmap_write(tc->regmap, PPI_D1S_ATMR, 0); regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE); diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 839b8832b9b5..7c0cbe84611b 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -15,7 +15,6 @@ #include <linux/slab.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index 91b5e1207c47..19316994ddd1 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -23,7 +23,6 @@ #include <drm/display/drm_dp_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> |