diff --git a/msm/dsi/dsi_catalog.h b/msm/dsi/dsi_catalog.h index a364f36e1c..c89aa728bd 100644 --- a/msm/dsi/dsi_catalog.h +++ b/msm/dsi/dsi_catalog.h @@ -164,7 +164,9 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, enum dsi_test_pattern type, u32 init_val, u32 stream_id); -void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable); +void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable, + enum dsi_ctrl_tpg_pattern pattern, + enum dsi_op_mode panel_mode); void dsi_ctrl_hw_cmn_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl, u32 stream_id); diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index ba522e0b77..120f15fcd3 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -3741,7 +3741,9 @@ error: * * Return: error code. */ -int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on) +int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on, + enum dsi_test_pattern type, u32 init_val, + enum dsi_ctrl_tpg_pattern pattern) { int rc = 0; @@ -3760,19 +3762,13 @@ int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on) } if (on) { - if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) { - dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw, - DSI_TEST_PATTERN_INC, - 0xFFFF); - } else { - dsi_ctrl->hw.ops.cmd_test_pattern_setup( - &dsi_ctrl->hw, - DSI_TEST_PATTERN_INC, - 0xFFFF, - 0x0); - } + if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) + dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw, type, init_val); + else + dsi_ctrl->hw.ops.cmd_test_pattern_setup(&dsi_ctrl->hw, type, init_val, 0x0); } - dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on); + dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on, pattern, + dsi_ctrl->host_config.panel_mode); DSI_CTRL_DEBUG(dsi_ctrl, "Set test pattern state=%d\n", on); dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_TPG, on); @@ -3781,6 +3777,30 @@ error: return rc; } +/** + * dsi_ctrl_trigger_test_pattern() - trigger a command mode frame update with test pattern + * @dsi_ctrl: DSI controller handle. + * + * Trigger a command mode frame update with chosen test pattern. + * + * Return: error code. + */ +int dsi_ctrl_trigger_test_pattern(struct dsi_ctrl *dsi_ctrl) +{ + int ret = 0; + + if (!dsi_ctrl) { + DSI_CTRL_ERR(dsi_ctrl, "Invalid params\n"); + return -EINVAL; + } + + mutex_lock(&dsi_ctrl->ctrl_lock); + dsi_ctrl->hw.ops.trigger_cmd_test_pattern(&dsi_ctrl->hw, 0); + mutex_unlock(&dsi_ctrl->ctrl_lock); + + return ret; +} + /** * dsi_ctrl_set_host_engine_state() - set host engine state * @dsi_ctrl: DSI Controller handle. diff --git a/msm/dsi/dsi_ctrl.h b/msm/dsi/dsi_ctrl.h index b1a5a90081..4735650a4e 100644 --- a/msm/dsi/dsi_ctrl.h +++ b/msm/dsi/dsi_ctrl.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -573,13 +574,28 @@ int dsi_ctrl_set_roi(struct dsi_ctrl *dsi_ctrl, struct dsi_rect *roi, * dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller * @dsi_ctrl: DSI controller handle. * @on: enable/disable test pattern. + * @type: type of test pattern to generate. + * @init_val: seed value for generating test pattern. + * @pattern: test pattern to generate. * * Test pattern can be enabled only after Video engine (for video mode panels) * or command engine (for cmd mode panels) is enabled. * * Return: error code. */ -int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on); +int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on, + enum dsi_test_pattern type, u32 init_val, + enum dsi_ctrl_tpg_pattern pattern); + +/** + * dsi_ctrl_trigger_test_pattern() - trigger a command mode frame update with test pattern + * @dsi_ctrl: DSI controller handle. + * + * Trigger a command mode frame update with chosen test pattern. + * + * Return: error code. + */ +int dsi_ctrl_trigger_test_pattern(struct dsi_ctrl *dsi_ctrl); /** * dsi_ctrl_transfer_prepare() - Set up a command transfer diff --git a/msm/dsi/dsi_ctrl_hw.h b/msm/dsi/dsi_ctrl_hw.h index ee01df53b9..2559e906fa 100644 --- a/msm/dsi/dsi_ctrl_hw.h +++ b/msm/dsi/dsi_ctrl_hw.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -41,6 +42,29 @@ */ #define DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER 0x1 +/** + * enum dsi_ctrl_tpg_pattern - type of TPG pattern + * @DSI_CTRL_TPG_COUNTER: + * @DSI_CTRL_TPG_FIXED: + * @DSI_CTRL_TPG_COLOR_RAMP_64L_64P: + * @DSI_CTRL_TPG_COLOR_RAMP_64L_256P: + * @DSI_CTRL_TPG_GRAYSCALE_RAMP: + * @DSI_CTRL_TPG_COLOR_SQUARE: + * @DSI_CTRL_TPG_CHECKERED_RECTANGLE: + * @DSI_CTRL_TPG_BASIC_COLOR_CHANGING: + */ +enum dsi_ctrl_tpg_pattern { + DSI_CTRL_TPG_COUNTER = 0, + DSI_CTRL_TPG_FIXED, + DSI_CTRL_TPG_COLOR_RAMP_64L_64P, + DSI_CTRL_TPG_COLOR_RAMP_64L_256P, + DSI_CTRL_TPG_BLACK_WHITE_VERTICAL_LINES, + DSI_CTRL_TPG_GRAYSCALE_RAMP, + DSI_CTRL_TPG_COLOR_SQUARE, + DSI_CTRL_TPG_CHECKERED_RECTANGLE, + DSI_CTRL_TPG_BASIC_COLOR_CHANGING +}; + /** * enum dsi_ctrl_version - version of the dsi host controller * @DSI_CTRL_VERSION_UNKNOWN: Unknown controller version @@ -92,12 +116,14 @@ enum dsi_ctrl_hw_features { * @DSI_TEST_PATTERN_FIXED: Test pattern is fixed, based on init value. * @DSI_TEST_PATTERN_INC: Incremental test pattern, base on init value. * @DSI_TEST_PATTERN_POLY: Pattern generated from polynomial and init val. + * @DSI_TEST_PATTERN_GENERAL: MDSS general test pattern. * @DSI_TEST_PATTERN_MAX: */ enum dsi_test_pattern { DSI_TEST_PATTERN_FIXED = 0, DSI_TEST_PATTERN_INC, DSI_TEST_PATTERN_POLY, + DSI_TEST_PATTERN_GENERAL, DSI_TEST_PATTERN_MAX }; @@ -727,8 +753,12 @@ struct dsi_ctrl_hw_ops { * test_pattern_enable() - enable test pattern engine * @ctrl: Pointer to the controller host hardware. * @enable: Enable/Disable test pattern engine. + * @pattern: Type of TPG pattern + * @panel_mode: DSI operation mode */ - void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable); + void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable, + enum dsi_ctrl_tpg_pattern pattern, + enum dsi_op_mode panel_mode); /** * clear_phy0_ln_err() - clear DSI PHY lane-0 errors diff --git a/msm/dsi/dsi_ctrl_hw_cmn.c b/msm/dsi/dsi_ctrl_hw_cmn.c index 1045e31e7e..576ab9985f 100644 --- a/msm/dsi/dsi_ctrl_hw_cmn.c +++ b/msm/dsi/dsi_ctrl_hw_cmn.c @@ -1516,20 +1516,23 @@ void dsi_ctrl_hw_cmn_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl, enum dsi_test_pattern type, u32 init_val) { - u32 reg = 0; + u32 reg = 0, pattern_sel_shift = 4; DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL, init_val); switch (type) { case DSI_TEST_PATTERN_FIXED: - reg |= (0x2 << 4); + reg |= (0x2 << pattern_sel_shift); break; case DSI_TEST_PATTERN_INC: - reg |= (0x1 << 4); + reg |= (0x1 << pattern_sel_shift); break; case DSI_TEST_PATTERN_POLY: DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_POLY, 0xF0F0F); break; + case DSI_TEST_PATTERN_GENERAL: + reg |= (0x3 << pattern_sel_shift); + break; default: break; } @@ -1590,6 +1593,9 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, case DSI_TEST_PATTERN_POLY: DSI_W32(ctrl, poly_offset, 0xF0F0F); break; + case DSI_TEST_PATTERN_GENERAL: + reg |= (0x3 << pattern_sel_shift); + break; default: break; } @@ -1602,11 +1608,28 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, * test_pattern_enable() - enable test pattern engine * @ctrl: Pointer to the controller host hardware. * @enable: Enable/Disable test pattern engine. + * @pattern: Type of TPG pattern + * @panel_mode: DSI operation mode */ void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, - bool enable) + bool enable, enum dsi_ctrl_tpg_pattern pattern, + enum dsi_op_mode panel_mode) { u32 reg = DSI_R32(ctrl, DSI_TEST_PATTERN_GEN_CTRL); + u32 reg_tpg_main_control = 0; + u32 reg_tpg_video_config = BIT(0); + + reg_tpg_video_config |= BIT(2); + + if (panel_mode == DSI_OP_CMD_MODE) { + reg_tpg_main_control = BIT(pattern); + DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL2, reg_tpg_main_control); + } else { + reg_tpg_main_control = BIT(pattern + 1); + DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL, reg_tpg_main_control); + } + + DSI_W32(ctrl, DSI_TPG_VIDEO_CONFIG, reg_tpg_video_config); if (enable) reg |= BIT(0); diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index aa01890d20..2f442bd42f 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -7763,7 +7763,10 @@ error: return rc; } -int dsi_display_set_tpg_state(struct dsi_display *display, bool enable) +int dsi_display_set_tpg_state(struct dsi_display *display, bool enable, + enum dsi_test_pattern type, + u32 init_val, + enum dsi_ctrl_tpg_pattern pattern) { int rc = 0; int i; @@ -7776,12 +7779,18 @@ int dsi_display_set_tpg_state(struct dsi_display *display, bool enable) display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; - rc = dsi_ctrl_set_tpg_state(ctrl->ctrl, enable); + rc = dsi_ctrl_set_tpg_state(ctrl->ctrl, enable, type, init_val, pattern); if (rc) { - DSI_ERR("[%s] failed to set tpg state for host_%d\n", - display->name, i); + DSI_ERR("[%s] failed to set tpg state for host_%d\n", display->name, i); goto error; } + if (enable && ctrl->ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) { + rc = dsi_ctrl_trigger_test_pattern(ctrl->ctrl); + if (rc) { + DSI_ERR("[%s] failed to start tpg for host_%d\n", display->name, i); + goto error; + } + } } display->is_tpg_enabled = enable; diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 5bdca42943..ea7b5055a7 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -633,7 +634,10 @@ int dsi_pre_clkon_cb(void *priv, enum dsi_clk_type clk_type, */ int dsi_display_unprepare(struct dsi_display *display); -int dsi_display_set_tpg_state(struct dsi_display *display, bool enable); +int dsi_display_set_tpg_state(struct dsi_display *display, bool enable, + enum dsi_test_pattern type, + u32 init_val, + enum dsi_ctrl_tpg_pattern pattern); int dsi_display_clock_gate(struct dsi_display *display, bool enable); int dsi_dispaly_static_frame(struct dsi_display *display, bool enable);