diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:40 +0000 |
commit | 8b0a8165cdad0f4133837d753649ef4682e42c3b (patch) | |
tree | 5c58f869f31ddb1f7bd6e8bdea269b680b36c5b6 /drivers/gpu/drm/msm/dsi | |
parent | Releasing progress-linux version 6.8.12-1~progress7.99u1. (diff) | |
download | linux-8b0a8165cdad0f4133837d753649ef4682e42c3b.tar.xz linux-8b0a8165cdad0f4133837d753649ef4682e42c3b.zip |
Merging upstream version 6.9.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu/drm/msm/dsi')
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.h | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_host.c | 61 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_manager.c | 65 |
4 files changed, 58 insertions, 100 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index c6bd7bf156..37c4c07005 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -216,6 +216,7 @@ void __exit msm_dsi_unregister(void) int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoder) { + struct drm_bridge *bridge; int ret; msm_dsi->dev = dev; @@ -235,15 +236,14 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, return 0; } - msm_dsi->encoder = encoder; - - ret = msm_dsi_manager_bridge_init(msm_dsi); - if (ret) { + bridge = msm_dsi_manager_bridge_init(msm_dsi, encoder); + if (IS_ERR(bridge)) { + ret = PTR_ERR(bridge); DRM_DEV_ERROR(dev->dev, "failed to create dsi bridge: %d\n", ret); return ret; } - ret = msm_dsi_manager_ext_bridge_init(msm_dsi->id); + ret = msm_dsi_manager_ext_bridge_init(msm_dsi->id, bridge); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dsi connector: %d\n", ret); diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 28379b1af6..2ad9a842c6 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -35,41 +35,25 @@ struct msm_dsi { struct drm_device *dev; struct platform_device *pdev; - /* internal dsi bridge attached to MDP interface */ - struct drm_bridge *bridge; - struct mipi_dsi_host *host; struct msm_dsi_phy *phy; - /* - * external_bridge connected to dsi bridge output - */ - struct drm_bridge *external_bridge; - struct device *phy_dev; bool phy_enabled; - /* the encoder we are hooked to (outside of dsi block) */ - struct drm_encoder *encoder; - int id; }; /* dsi manager */ -int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi); -int msm_dsi_manager_ext_bridge_init(u8 id); +struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi, + struct drm_encoder *encoder); +int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge); int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); int msm_dsi_manager_register(struct msm_dsi *msm_dsi); void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); void msm_dsi_manager_tpg_enable(void); -/* msm dsi */ -static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi) -{ - return msm_dsi->external_bridge; -} - /* dsi host */ struct msm_dsi_host; int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host, diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index deeecdfd6c..c80be74cf1 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -183,16 +183,6 @@ struct msm_dsi_host { int irq; }; -static u32 dsi_get_bpp(const enum mipi_dsi_pixel_format fmt) -{ - switch (fmt) { - case MIPI_DSI_FMT_RGB565: return 16; - case MIPI_DSI_FMT_RGB666_PACKED: return 18; - case MIPI_DSI_FMT_RGB666: - case MIPI_DSI_FMT_RGB888: - default: return 24; - } -} static inline u32 dsi_read(struct msm_dsi_host *msm_host, u32 reg) { @@ -366,8 +356,8 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) { int ret; - DBG("Set clk rates: pclk=%d, byteclk=%lu", - msm_host->mode->clock, msm_host->byte_clk_rate); + DBG("Set clk rates: pclk=%lu, byteclk=%lu", + msm_host->pixel_clk_rate, msm_host->byte_clk_rate); ret = dev_pm_opp_set_rate(&msm_host->pdev->dev, msm_host->byte_clk_rate); @@ -440,9 +430,9 @@ int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host) { int ret; - DBG("Set clk rates: pclk=%d, byteclk=%lu, esc_clk=%lu, dsi_src_clk=%lu", - msm_host->mode->clock, msm_host->byte_clk_rate, - msm_host->esc_clk_rate, msm_host->src_clk_rate); + DBG("Set clk rates: pclk=%lu, byteclk=%lu, esc_clk=%lu, dsi_src_clk=%lu", + msm_host->pixel_clk_rate, msm_host->byte_clk_rate, + msm_host->esc_clk_rate, msm_host->src_clk_rate); ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate); if (ret) { @@ -529,6 +519,25 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->byte_clk); } +/** + * dsi_adjust_pclk_for_compression() - Adjust the pclk rate for compression case + * @mode: The selected mode for the DSI output + * @dsc: DRM DSC configuration for this DSI output + * + * Adjust the pclk rate by calculating a new hdisplay proportional to + * the compression ratio such that: + * new_hdisplay = old_hdisplay * compressed_bpp / uncompressed_bpp + * + * Porches do not need to be adjusted: + * - For VIDEO mode they are not compressed by DSC and are passed as is. + * - For CMD mode there are no actual porches. Instead these fields + * currently represent the overhead to the image data transfer. As such, they + * are calculated for the final mode parameters (after the compression) and + * are not to be adjusted too. + * + * FIXME: Reconsider this if/when CMD mode handling is rewritten to use + * transfer time and data overhead as a starting point of the calculations. + */ static unsigned long dsi_adjust_pclk_for_compression(const struct drm_display_mode *mode, const struct drm_dsc_config *dsc) { @@ -567,7 +576,7 @@ unsigned long dsi_byte_clk_get_rate(struct mipi_dsi_host *host, bool is_bonded_d { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); u8 lanes = msm_host->lanes; - u32 bpp = dsi_get_bpp(msm_host->format); + u32 bpp = mipi_dsi_pixel_format_to_bpp(msm_host->format); unsigned long pclk_rate = dsi_get_pclk_rate(mode, msm_host->dsc, is_bonded_dsi); unsigned long pclk_bpp; @@ -610,7 +619,7 @@ int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi) int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi) { - u32 bpp = dsi_get_bpp(msm_host->format); + u32 bpp = mipi_dsi_pixel_format_to_bpp(msm_host->format); unsigned int esc_mhz, esc_div; unsigned long byte_mhz; @@ -951,8 +960,18 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) if (ret) return; - /* Divide the display by 3 but keep back/font porch and - * pulse width same + /* + * DPU sends 3 bytes per pclk cycle to DSI. If widebus is + * enabled, bus width is extended to 6 bytes. + * + * Calculate the number of pclks needed to transmit one line of + * the compressed data. + + * The back/font porch and pulse width are kept intact. For + * VIDEO mode they represent timing parameters rather than + * actual data transfer, see the documentation for + * dsi_adjust_pclk_for_compression(). For CMD mode they are + * unused anyway. */ h_total -= hdisplay; if (wide_bus_enabled && !(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) @@ -993,7 +1012,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) /* image data and 1 byte write_memory_start cmd */ if (!msm_host->dsc) - wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; + wc = hdisplay * mipi_dsi_pixel_format_to_bpp(msm_host->format) / 8 + 1; else /* * When DSC is enabled, WC = slice_chunk_size * slice_per_pkt + 1. @@ -1413,7 +1432,7 @@ static int dsi_cmds2buf_tx(struct msm_dsi_host *msm_host, { int len, ret; int bllp_len = msm_host->mode->hdisplay * - dsi_get_bpp(msm_host->format) / 8; + mipi_dsi_pixel_format_to_bpp(msm_host->format) / 8; len = dsi_cmd_dma_add(msm_host, msg); if (len < 0) { diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 896f369fdd..af2a287cb3 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -198,36 +198,6 @@ static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge) return dsi_bridge->id; } -static void msm_dsi_manager_set_split_display(u8 id) -{ - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); - struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); - struct msm_drm_private *priv = msm_dsi->dev->dev_private; - struct msm_kms *kms = priv->kms; - struct msm_dsi *master_dsi, *slave_dsi; - - if (IS_BONDED_DSI() && !IS_MASTER_DSI_LINK(id)) { - master_dsi = other_dsi; - slave_dsi = msm_dsi; - } else { - master_dsi = msm_dsi; - slave_dsi = other_dsi; - } - - if (!msm_dsi->external_bridge || !IS_BONDED_DSI()) - return; - - /* - * Set split display info to kms once bonded DSI panel is connected to - * both hosts. - */ - if (other_dsi && other_dsi->external_bridge && kms->funcs->set_split_display) { - kms->funcs->set_split_display(kms, master_dsi->encoder, - slave_dsi->encoder, - msm_dsi_is_cmd_mode(msm_dsi)); - } -} - static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge) { int id = dsi_mgr_bridge_get_id(bridge); @@ -305,8 +275,6 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) int ret; DBG("id=%d", id); - if (!msm_dsi_device_connected(msm_dsi)) - return; /* Do nothing with the host if it is slave-DSI in case of bonded DSI */ if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id)) @@ -364,9 +332,6 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) DBG("id=%d", id); - if (!msm_dsi_device_connected(msm_dsi)) - return; - /* * Do nothing with the host if it is slave-DSI in case of bonded DSI. * It is safe to call dsi_mgr_phy_disable() here because a single PHY @@ -466,55 +431,48 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { }; /* initialize bridge */ -int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) +struct drm_bridge *msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi, + struct drm_encoder *encoder) { - struct drm_bridge *bridge = NULL; + struct drm_bridge *bridge; struct dsi_bridge *dsi_bridge; - struct drm_encoder *encoder; int ret; dsi_bridge = devm_kzalloc(msm_dsi->dev->dev, sizeof(*dsi_bridge), GFP_KERNEL); if (!dsi_bridge) - return -ENOMEM; + return ERR_PTR(-ENOMEM); dsi_bridge->id = msm_dsi->id; - encoder = msm_dsi->encoder; - bridge = &dsi_bridge->base; bridge->funcs = &dsi_mgr_bridge_funcs; ret = devm_drm_bridge_add(msm_dsi->dev->dev, bridge); if (ret) - return ret; + return ERR_PTR(ret); ret = drm_bridge_attach(encoder, bridge, NULL, 0); if (ret) - return ret; - - msm_dsi->bridge = bridge; + return ERR_PTR(ret); - return 0; + return bridge; } -int msm_dsi_manager_ext_bridge_init(u8 id) +int msm_dsi_manager_ext_bridge_init(u8 id, struct drm_bridge *int_bridge) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_device *dev = msm_dsi->dev; struct drm_encoder *encoder; - struct drm_bridge *int_bridge, *ext_bridge; + struct drm_bridge *ext_bridge; int ret; - int_bridge = msm_dsi->bridge; ext_bridge = devm_drm_of_get_bridge(&msm_dsi->pdev->dev, msm_dsi->pdev->dev.of_node, 1, 0); if (IS_ERR(ext_bridge)) return PTR_ERR(ext_bridge); - msm_dsi->external_bridge = ext_bridge; - - encoder = msm_dsi->encoder; + encoder = int_bridge->encoder; /* * Try first to create the bridge without it creating its own @@ -546,9 +504,6 @@ int msm_dsi_manager_ext_bridge_init(u8 id) return ret; } - /* The pipeline is ready, ping encoders if necessary */ - msm_dsi_manager_set_split_display(id); - return 0; } |