diff options
author | Kwanghyun Chung <khyun.chung@samsung.com> | 2021-08-05 17:14:13 +0900 |
---|---|---|
committer | Ken Huang <kenbshuang@google.com> | 2021-09-23 10:12:44 +0000 |
commit | b7e3953075763bcb01d033c1b061c836862bc5e8 (patch) | |
tree | 04265ee81e40fa8c381866d4bcd68518a1d4ed65 /samsung/exynos_drm_dsim.c | |
parent | 002e790d8bf703f0a896333721738662878e74a4 (diff) | |
download | display-b7e3953075763bcb01d033c1b061c836862bc5e8.tar.gz |
drm: samsung: support dual dsi
This patch supports dual dsi for the panel spec below.
1. Video mode
2. No DSC
3. 2 ports, 8lanes, DPHY
Bug: 193602257
Signed-off-by: Kwanghyun Chung <khyun.chung@samsung.com>
Change-Id: I224013682aebab9afdf6cec13fa7d3ca60389e53
Signed-off-by: Ken Huang <kenbshuang@google.com>
Diffstat (limited to 'samsung/exynos_drm_dsim.c')
-rw-r--r-- | samsung/exynos_drm_dsim.c | 86 |
1 files changed, 82 insertions, 4 deletions
diff --git a/samsung/exynos_drm_dsim.c b/samsung/exynos_drm_dsim.c index 7006931..bbc004a 100644 --- a/samsung/exynos_drm_dsim.c +++ b/samsung/exynos_drm_dsim.c @@ -249,6 +249,7 @@ static void dsim_set_te_pinctrl(struct dsim_device *dsim, bool en) static void _dsim_enable(struct dsim_device *dsim) { const struct decon_device *decon = dsim_get_decon(dsim); + struct dsim_device *sec_dsi; pm_runtime_get_sync(dsim->dev); @@ -285,6 +286,14 @@ static void _dsim_enable(struct dsim_device *dsim) DPU_EVENT_LOG(DPU_EVT_DSIM_ENABLED, decon->id, dsim); dsim_debug(dsim, "%s -\n", __func__); + + if (dsim->dual_dsi == DSIM_DUAL_DSI_MAIN) { + sec_dsi = exynos_get_dual_dsi(DSIM_DUAL_DSI_SEC); + if (sec_dsi) + _dsim_enable(sec_dsi); + else + dsim_err(dsim, "could not get secondary dsi\n"); + } } static void dsim_encoder_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) @@ -362,6 +371,15 @@ static void _dsim_enter_ulps_locked(struct dsim_device *dsim) static void _dsim_disable(struct dsim_device *dsim) { const struct decon_device *decon = dsim_get_decon(dsim); + struct dsim_device *sec_dsi; + + if (dsim->dual_dsi == DSIM_DUAL_DSI_MAIN) { + sec_dsi = exynos_get_dual_dsi(DSIM_DUAL_DSI_SEC); + if (sec_dsi) + _dsim_disable(sec_dsi); + else + dsim_err(dsim, "could not get secondary dsi\n"); + } dsim_debug(dsim, "+\n"); mutex_lock(&dsim->state_lock); @@ -957,6 +975,8 @@ static void dsim_update_config_for_mode(struct dsim_reg_config *config, p_timing->vsa = vm.vsync_len; p_timing->hactive = vm.hactive; + if (config->dual_dsi) + p_timing->hactive /= 2; p_timing->hfp = vm.hfront_porch; p_timing->hbp = vm.hback_porch; p_timing->hsa = vm.hsync_len; @@ -992,6 +1012,8 @@ static void dsim_set_display_mode(struct dsim_device *dsim, const struct drm_display_mode *mode, const struct exynos_display_mode *exynos_mode) { + struct dsim_device *sec_dsi; + if (!dsim->dsi_device) return; @@ -999,6 +1021,7 @@ static void dsim_set_display_mode(struct dsim_device *dsim, dsim->config.data_lane_cnt = dsim->dsi_device->lanes; dsim->hw_trigger = !exynos_mode->sw_trigger; + dsim->config.dual_dsi = dsim->dual_dsi; dsim_update_config_for_mode(&dsim->config, mode, exynos_mode); dsim_set_clock_mode(dsim, mode); @@ -1014,6 +1037,15 @@ static void dsim_set_display_mode(struct dsim_device *dsim, dsim->config.dsc.slice_width, dsim->config.dsc.slice_height); mutex_unlock(&dsim->state_lock); + + if (dsim->dual_dsi == DSIM_DUAL_DSI_MAIN) { + sec_dsi = exynos_get_dual_dsi(DSIM_DUAL_DSI_SEC); + if (sec_dsi) { + sec_dsi->dsi_device = dsim->dsi_device; + dsim_set_display_mode(sec_dsi, mode, exynos_mode); + } else + dsim_err(dsim, "could not get main dsi\n"); + } } static void dsim_atomic_mode_set(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, @@ -1159,6 +1191,7 @@ static int dsim_add_mipi_dsi_device(struct dsim_device *dsim, const char *pname) }; struct device_node *node; const char *name; + const char *dual_dsi; dsim_debug(dsim, "preferred panel is %s\n", pname); @@ -1196,7 +1229,16 @@ static int dsim_add_mipi_dsi_device(struct dsim_device *dsim, const char *pname) } if (info.node) { - mipi_dsi_device_register_full(&dsim->dsi_host, &info); + if (!of_property_read_string(info.node, "dual-dsi", &dual_dsi)) { + if (!strcmp(dual_dsi, "main")) + dsim->dual_dsi = DSIM_DUAL_DSI_MAIN; + else if (!strcmp(dual_dsi, "sec")) + dsim->dual_dsi = DSIM_DUAL_DSI_SEC; + else + dsim->dual_dsi = DSIM_DUAL_DSI_NONE; + } + if (dsim->dual_dsi != DSIM_DUAL_DSI_SEC) + mipi_dsi_device_register_full(&dsim->dsi_host, &info); return 0; } @@ -1254,6 +1296,12 @@ static int dsim_bind(struct device *dev, struct device *master, void *data) dsim_debug(dsim, "%s +\n", __func__); + /* parse the panel name to select the dsi device for the detected panel */ + dsim_parse_panel_name(dsim); + + if (dsim->dual_dsi == DSIM_DUAL_DSI_SEC) + return 0; + drm_encoder_init(drm_dev, encoder, &dsim_encoder_funcs, DRM_MODE_ENCODER_DSI, NULL); drm_encoder_helper_add(encoder, &dsim_encoder_helper_funcs); @@ -1266,9 +1314,6 @@ static int dsim_bind(struct device *dev, struct device *master, void *data) return -ENOTSUPP; } - /* parse the panel name to select the dsi device for the detected panel */ - dsim_parse_panel_name(dsim); - ret = mipi_dsi_host_register(&dsim->dsi_host); dsim_debug(dsim, "%s -\n", __func__); @@ -1286,6 +1331,9 @@ static void dsim_unbind(struct device *dev, struct device *master, if (dsim->pll_params) dsim_modes_release(dsim->pll_params); + if (dsim->dual_dsi == DSIM_DUAL_DSI_SEC) + return; + mipi_dsi_host_unregister(&dsim->dsi_host); } @@ -1964,10 +2012,33 @@ dsim_read_data(struct dsim_device *dsim, const struct mipi_dsi_msg *msg) return rx_size; } +static int +dsim_write_data_dual(struct dsim_device *dsim, const struct mipi_dsi_msg *msg) +{ + int ret; + + ret = pm_runtime_resume_and_get(dsim->dev); + if (ret) { + dsim_err(dsim, "runtime resume failed (%d). unable to transfer cmd\n", ret); + return ret; + } + + mutex_lock(&dsim->cmd_lock); + + ret = dsim_write_data(dsim, msg); + + mutex_unlock(&dsim->cmd_lock); + + pm_runtime_mark_last_busy(dsim->dev); + pm_runtime_put_sync_autosuspend(dsim->dev); + + return ret; +} static ssize_t dsim_host_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_msg *msg) { struct dsim_device *dsim = host_to_dsi(host); + struct dsim_device *sec_dsi; int ret; DPU_ATRACE_BEGIN(__func__); @@ -1993,6 +2064,13 @@ static ssize_t dsim_host_transfer(struct mipi_dsi_host *host, break; default: ret = dsim_write_data(dsim, msg); + if (dsim->dual_dsi == DSIM_DUAL_DSI_MAIN) { + sec_dsi = exynos_get_dual_dsi(DSIM_DUAL_DSI_SEC); + if (sec_dsi) + ret = dsim_write_data_dual(sec_dsi, msg); + else + dsim_err(dsim, "could not get secondary dsi\n"); + } break; } |