diff options
author | Dave Airlie <airlied@redhat.com> | 2023-10-23 11:29:18 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2023-10-23 11:29:18 +0300 |
commit | 3f5ba636d6987ddffeaa056dea1c524da63912f3 (patch) | |
tree | 7e30f36deb4a566fdb4b24113d486633b694d270 /drivers/gpu/drm/msm/dsi | |
parent | 7cd62eab9babd1fed9c497141650b31168f4f430 (diff) | |
parent | b08d26dac1a1075c874f40ee02ec8ddc39e20146 (diff) | |
download | linux-3f5ba636d6987ddffeaa056dea1c524da63912f3.tar.xz |
Merge tag 'drm-msm-next-2023-10-17' of https://gitlab.freedesktop.org/drm/msm into drm-next
Updates for v6.7
DP:
- use existing helpers for DPCD handling instead of open-coded functions
- set the subconnector type according to the plugged cable / dongle
skip validity check for DP CTS EDID checksum
DPU:
- continued migration of feature flags to use core revision checks
- reworked interrupts code to use '0' as NO_IRQ, removed raw IRQ indices
from log / trace output
gpu:
- a7xx support (a730, a740)
- fixes and additional speedbins for a635, a643
core:
- decouple msm_drv from kms to more cleanly support headless devices (like
imx5+a2xx)
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGvzkBL2_OgyOeP_b6rVEjrNdfm8jcKzaB04HqHyT5jYwA@mail.gmail.com
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/msm/dsi')
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.xml.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_host.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_manager.c | 30 |
5 files changed, 61 insertions, 56 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 7a8208cd6649..c6bd7bf15605 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -17,6 +17,11 @@ struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) return msm_dsi_host_get_dsc_config(msm_dsi->host); } +bool msm_dsi_wide_bus_enabled(struct msm_dsi *msm_dsi) +{ + return msm_dsi_host_is_wide_bus_enabled(msm_dsi->host); +} + static int dsi_get_phy(struct msm_dsi *msm_dsi) { struct platform_device *pdev = msm_dsi->pdev; @@ -126,6 +131,7 @@ static void dsi_unbind(struct device *dev, struct device *master, struct msm_drm_private *priv = dev_get_drvdata(master); struct msm_dsi *msm_dsi = dev_get_drvdata(dev); + msm_dsi_tx_buf_free(msm_dsi->host); priv->dsi[msm_dsi->id] = NULL; } @@ -210,20 +216,14 @@ 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 msm_drm_private *priv = dev->dev_private; int ret; - if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) { - DRM_DEV_ERROR(dev->dev, "too many bridges\n"); - return -ENOSPC; - } - msm_dsi->dev = dev; ret = msm_dsi_host_modeset_init(msm_dsi->host, dev); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to modeset init host: %d\n", ret); - goto fail; + return ret; } if (msm_dsi_is_bonded_dsi(msm_dsi) && @@ -237,32 +237,20 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, msm_dsi->encoder = encoder; - msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id); - if (IS_ERR(msm_dsi->bridge)) { - ret = PTR_ERR(msm_dsi->bridge); + ret = msm_dsi_manager_bridge_init(msm_dsi); + if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dsi bridge: %d\n", ret); - msm_dsi->bridge = NULL; - goto fail; + return ret; } ret = msm_dsi_manager_ext_bridge_init(msm_dsi->id); if (ret) { DRM_DEV_ERROR(dev->dev, "failed to create dsi connector: %d\n", ret); - goto fail; + return ret; } - priv->bridges[priv->num_bridges++] = msm_dsi->bridge; - return 0; -fail: - /* bridge/connector are normally destroyed by drm: */ - if (msm_dsi->bridge) { - msm_dsi_manager_bridge_destroy(msm_dsi->bridge); - msm_dsi->bridge = NULL; - } - - return ret; } void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index bd3763a5d723..28379b1af63f 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -56,8 +56,7 @@ struct msm_dsi { }; /* dsi manager */ -struct drm_bridge *msm_dsi_manager_bridge_init(u8 id); -void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge); +int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi); int msm_dsi_manager_ext_bridge_init(u8 id); 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); @@ -125,6 +124,7 @@ int dsi_tx_buf_alloc_v2(struct msm_dsi_host *msm_host, int size); void *dsi_tx_buf_get_6g(struct msm_dsi_host *msm_host); void *dsi_tx_buf_get_v2(struct msm_dsi_host *msm_host); void dsi_tx_buf_put_6g(struct msm_dsi_host *msm_host); +void msm_dsi_tx_buf_free(struct mipi_dsi_host *mipi_host); int dsi_dma_base_get_6g(struct msm_dsi_host *msm_host, uint64_t *iova); int dsi_dma_base_get_v2(struct msm_dsi_host *msm_host, uint64_t *iova); int dsi_clk_init_v2(struct msm_dsi_host *msm_host); @@ -134,6 +134,7 @@ int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi); void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct mipi_dsi_host *host); void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host); struct drm_dsc_config *msm_dsi_host_get_dsc_config(struct mipi_dsi_host *host); +bool msm_dsi_host_is_wide_bus_enabled(struct mipi_dsi_host *host); /* dsi phy */ struct msm_dsi_phy; diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h index a4a154601114..2a7d980e12c3 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h @@ -664,6 +664,7 @@ static inline uint32_t DSI_CMD_MODE_MDP_CTRL2_INPUT_RGB_SWAP(enum dsi_rgb_swap v return ((val) << DSI_CMD_MODE_MDP_CTRL2_INPUT_RGB_SWAP__SHIFT) & DSI_CMD_MODE_MDP_CTRL2_INPUT_RGB_SWAP__MASK; } #define DSI_CMD_MODE_MDP_CTRL2_BURST_MODE 0x00010000 +#define DSI_CMD_MODE_MDP_CTRL2_DATABUS_WIDEN 0x00100000 #define REG_DSI_CMD_MODE_MDP_STREAM2_CTRL 0x000001b8 #define DSI_CMD_MODE_MDP_STREAM2_CTRL_DATA_TYPE__MASK 0x0000003f diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 3d6fb708dc22..deeecdfd6c4e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -147,6 +147,7 @@ struct msm_dsi_host { /* DSI 6G TX buffer*/ struct drm_gem_object *tx_gem_obj; + struct msm_gem_address_space *aspace; /* DSI v2 TX buffer */ void *tx_buf; @@ -710,6 +711,15 @@ static void dsi_ctrl_disable(struct msm_dsi_host *msm_host) dsi_write(msm_host, REG_DSI_CTRL, 0); } +bool msm_dsi_host_is_wide_bus_enabled(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + return msm_host->dsc && + (msm_host->cfg_hnd->major == MSM_DSI_VER_MAJOR_6G && + msm_host->cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V2_5_0); +} + static void dsi_ctrl_enable(struct msm_dsi_host *msm_host, struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy *phy) { @@ -753,10 +763,16 @@ static void dsi_ctrl_enable(struct msm_dsi_host *msm_host, data |= DSI_CMD_CFG1_INSERT_DCS_COMMAND; dsi_write(msm_host, REG_DSI_CMD_CFG1, data); - if (msm_host->cfg_hnd->major == MSM_DSI_VER_MAJOR_6G && - msm_host->cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V1_3) { + if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) { data = dsi_read(msm_host, REG_DSI_CMD_MODE_MDP_CTRL2); - data |= DSI_CMD_MODE_MDP_CTRL2_BURST_MODE; + + if (cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V1_3) + data |= DSI_CMD_MODE_MDP_CTRL2_BURST_MODE; + + /* TODO: Allow for video-mode support once tested/fixed */ + if (msm_dsi_host_is_wide_bus_enabled(&msm_host->base)) + data |= DSI_CMD_MODE_MDP_CTRL2_DATABUS_WIDEN; + dsi_write(msm_host, REG_DSI_CMD_MODE_MDP_CTRL2, data); } } @@ -894,6 +910,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) u32 hdisplay = mode->hdisplay; u32 wc; int ret; + bool wide_bus_enabled = msm_dsi_host_is_wide_bus_enabled(&msm_host->base); DBG(""); @@ -914,6 +931,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) if (msm_host->dsc) { struct drm_dsc_config *dsc = msm_host->dsc; + u32 bytes_per_pclk; /* update dsc params with timing params */ if (!dsc || !mode->hdisplay || !mode->vdisplay) { @@ -937,7 +955,13 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) * pulse width same */ h_total -= hdisplay; - hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc), 3); + if (wide_bus_enabled && !(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) + bytes_per_pclk = 6; + else + bytes_per_pclk = 3; + + hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc), bytes_per_pclk); + h_total += hdisplay; ha_end = ha_start + hdisplay; } @@ -1111,8 +1135,10 @@ int dsi_tx_buf_alloc_6g(struct msm_dsi_host *msm_host, int size) uint64_t iova; u8 *data; + msm_host->aspace = msm_gem_address_space_get(priv->kms->aspace); + data = msm_gem_kernel_new(dev, size, MSM_BO_WC, - priv->kms->aspace, + msm_host->aspace, &msm_host->tx_gem_obj, &iova); if (IS_ERR(data)) { @@ -1141,10 +1167,10 @@ int dsi_tx_buf_alloc_v2(struct msm_dsi_host *msm_host, int size) return 0; } -static void dsi_tx_buf_free(struct msm_dsi_host *msm_host) +void msm_dsi_tx_buf_free(struct mipi_dsi_host *host) { + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); struct drm_device *dev = msm_host->dev; - struct msm_drm_private *priv; /* * This is possible if we're tearing down before we've had a chance to @@ -1155,11 +1181,11 @@ static void dsi_tx_buf_free(struct msm_dsi_host *msm_host) if (!dev) return; - priv = dev->dev_private; if (msm_host->tx_gem_obj) { - msm_gem_unpin_iova(msm_host->tx_gem_obj, priv->kms->aspace); - drm_gem_object_put(msm_host->tx_gem_obj); + msm_gem_kernel_put(msm_host->tx_gem_obj, msm_host->aspace); + msm_gem_address_space_put(msm_host->aspace); msm_host->tx_gem_obj = NULL; + msm_host->aspace = NULL; } if (msm_host->tx_buf) @@ -1945,7 +1971,6 @@ void msm_dsi_host_destroy(struct mipi_dsi_host *host) struct msm_dsi_host *msm_host = to_msm_dsi_host(host); DBG(""); - dsi_tx_buf_free(msm_host); if (msm_host->workqueue) { destroy_workqueue(msm_host->workqueue); msm_host->workqueue = NULL; diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 28b8012a21f2..896f369fdd53 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -466,9 +466,8 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { }; /* initialize bridge */ -struct drm_bridge *msm_dsi_manager_bridge_init(u8 id) +int msm_dsi_manager_bridge_init(struct msm_dsi *msm_dsi) { - struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_bridge *bridge = NULL; struct dsi_bridge *dsi_bridge; struct drm_encoder *encoder; @@ -476,31 +475,27 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id) dsi_bridge = devm_kzalloc(msm_dsi->dev->dev, sizeof(*dsi_bridge), GFP_KERNEL); - if (!dsi_bridge) { - ret = -ENOMEM; - goto fail; - } + if (!dsi_bridge) + return -ENOMEM; - dsi_bridge->id = id; + dsi_bridge->id = msm_dsi->id; encoder = msm_dsi->encoder; bridge = &dsi_bridge->base; bridge->funcs = &dsi_mgr_bridge_funcs; - drm_bridge_add(bridge); + ret = devm_drm_bridge_add(msm_dsi->dev->dev, bridge); + if (ret) + return ret; ret = drm_bridge_attach(encoder, bridge, NULL, 0); if (ret) - goto fail; + return ret; - return bridge; + msm_dsi->bridge = bridge; -fail: - if (bridge) - msm_dsi_manager_bridge_destroy(bridge); - - return ERR_PTR(ret); + return 0; } int msm_dsi_manager_ext_bridge_init(u8 id) @@ -557,11 +552,6 @@ int msm_dsi_manager_ext_bridge_init(u8 id) return 0; } -void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge) -{ - drm_bridge_remove(bridge); -} - int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); |