summaryrefslogtreecommitdiff
path: root/samsung/exynos_drm_dsim.c
diff options
context:
space:
mode:
authorKwanghyun Chung <khyun.chung@samsung.com>2021-08-05 17:14:13 +0900
committerKen Huang <kenbshuang@google.com>2021-09-23 10:12:44 +0000
commitb7e3953075763bcb01d033c1b061c836862bc5e8 (patch)
tree04265ee81e40fa8c381866d4bcd68518a1d4ed65 /samsung/exynos_drm_dsim.c
parent002e790d8bf703f0a896333721738662878e74a4 (diff)
downloaddisplay-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.c86
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;
}