Merge branch 'display-kernel.lnx.5.10' into display-kernel.lnx.1.0

Change-Id: I5d2b08380b6b0eb09492b950fb38cd9a0b3196c1
This commit is contained in:
Jeykumar Sankaran
2021-12-08 12:37:35 -08:00
53 changed files with 1867 additions and 334 deletions

View File

@@ -922,6 +922,19 @@ static int dsi_display_status_check_te(struct dsi_display *display,
return rc;
}
void dsi_display_toggle_error_interrupt_status(struct dsi_display * display, bool enable)
{
int i = 0;
struct dsi_display_ctrl *ctrl;
display_for_each_ctrl(i, display) {
ctrl = &display->ctrl[i];
if (!ctrl->ctrl)
continue;
dsi_ctrl_toggle_error_interrupt_status(ctrl->ctrl, enable);
}
}
int dsi_display_check_status(struct drm_connector *connector, void *display,
bool te_check_override)
{
@@ -967,6 +980,11 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
dsi_display_set_ctrl_esd_check_flag(dsi_display, true);
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_ON);
/* Disable error interrupts while doing an ESD check */
dsi_display_toggle_error_interrupt_status(dsi_display, false);
if (status_mode == ESD_MODE_REG_READ) {
rc = dsi_display_status_reg_read(dsi_display);
} else if (status_mode == ESD_MODE_SW_BTA) {
@@ -991,7 +1009,11 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
/* Handle Panel failures during display disable sequence */
if (rc <=0)
atomic_set(&panel->esd_recovery_pending, 1);
else
/* Enable error interrupts post an ESD success */
dsi_display_toggle_error_interrupt_status(dsi_display, true);
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_OFF);
release_panel_lock:
dsi_panel_release_panel_lock(panel);
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT, rc);
@@ -1041,18 +1063,23 @@ static int dsi_display_cmd_rx(struct dsi_display *display,
flags = DSI_CTRL_CMD_READ;
dsi_display_clk_ctrl(display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_ON);
dsi_display_toggle_error_interrupt_status(display, false);
cmd->ctrl_flags = flags;
dsi_display_set_cmd_tx_ctrl_flags(display, cmd);
rc = dsi_ctrl_transfer_prepare(m_ctrl->ctrl, cmd->ctrl_flags);
if (rc) {
DSI_ERR("prepare for rx cmd transfer failed rc = %d\n", rc);
goto release_panel_lock;
goto enable_error_interrupts;
}
rc = dsi_ctrl_cmd_transfer(m_ctrl->ctrl, cmd);
if (rc <= 0)
DSI_ERR("rx cmd transfer failed rc = %d\n", rc);
dsi_ctrl_transfer_unprepare(m_ctrl->ctrl, cmd->ctrl_flags);
enable_error_interrupts:
dsi_display_toggle_error_interrupt_status(display, true);
dsi_display_clk_ctrl(display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_OFF);
release_panel_lock:
dsi_panel_release_panel_lock(display->panel);
return rc;
@@ -1098,6 +1125,8 @@ int dsi_display_cmd_transfer(struct drm_connector *connector,
goto end;
}
SDE_EVT32(dsi_display->tx_cmd_buf_ndx, cmd_buf_len);
/*
* Reset the dbgfs buffer if the commands sent exceed the available
* buffer size. For video mode, limiting the buffer size to 2K to
@@ -1230,6 +1259,8 @@ int dsi_display_cmd_receive(void *display, const char *cmd_buf,
goto end;
}
SDE_EVT32(cmd_buf_len, recv_buf_len);
rc = dsi_display_cmd_rx(dsi_display, &cmd);
if (rc <= 0)
DSI_ERR("[DSI] Display command receive failed, rc=%d\n", rc);
@@ -3554,6 +3585,21 @@ static void dsi_display_ctrl_isr_configure(struct dsi_display *display, bool en)
}
}
static void dsi_display_cleanup_post_esd_failure(struct dsi_display *display)
{
int i = 0;
struct dsi_display_ctrl *ctrl;
display_for_each_ctrl(i, display) {
ctrl = &display->ctrl[i];
if (!ctrl->ctrl)
continue;
dsi_phy_lane_reset(ctrl->phy);
dsi_ctrl_soft_reset(ctrl->ctrl);
}
}
int dsi_pre_clkoff_cb(void *priv,
enum dsi_clk_type clk,
enum dsi_lclk_type l_type,
@@ -3565,6 +3611,14 @@ int dsi_pre_clkoff_cb(void *priv,
if ((clk & DSI_LINK_CLK) && (new_state == DSI_CLK_OFF) &&
(l_type & DSI_LINK_LP_CLK)) {
/*
* Clean up the DSI controller on a previous ESD failure. This requires a DSI
* controller soft reset. Also reset PHY lanes before resetting controller.
*/
if (atomic_read(&display->panel->esd_recovery_pending))
dsi_display_cleanup_post_esd_failure(display);
/*
* If continuous clock is enabled then disable it
* before entering into ULPS Mode.
@@ -3758,6 +3812,13 @@ int dsi_post_clkoff_cb(void *priv,
return -EINVAL;
}
/* Reset PHY to clear the PHY status once the HS clocks are turned off */
if ((clk_type & DSI_LINK_CLK) && (curr_state == DSI_CLK_OFF)
&& (l_type == DSI_LINK_HS_CLK)) {
if (atomic_read(&display->panel->esd_recovery_pending))
dsi_display_phy_sw_reset(display);
}
if ((clk_type & DSI_CORE_CLK) &&
(curr_state == DSI_CLK_OFF)) {
rc = dsi_display_phy_power_off(display);
@@ -4064,7 +4125,8 @@ error:
static bool dsi_display_validate_panel_resources(struct dsi_display *display)
{
if (!is_sim_panel(display)) {
if (!gpio_is_valid(display->panel->reset_config.reset_gpio)) {
if (!display->panel->host_config.ext_bridge_mode &&
!gpio_is_valid(display->panel->reset_config.reset_gpio)) {
DSI_ERR("invalid reset gpio for the panel\n");
return false;
}
@@ -6796,6 +6858,57 @@ static void _dsi_display_populate_bit_clks(struct dsi_display *display, int star
}
}
static int dsi_display_mode_dyn_clk_cpy(struct dsi_display *display,
struct dsi_display_mode *src, struct dsi_display_mode *dst)
{
int rc = 0;
u32 count = 0;
struct dsi_dyn_clk_caps *dyn_clk_caps;
struct msm_dyn_clk_list *bit_clk_list;
dyn_clk_caps = &(display->panel->dyn_clk_caps);
if (!dyn_clk_caps->dyn_clk_support)
return rc;
count = dst->priv_info->bit_clk_list.count;
bit_clk_list = &dst->priv_info->bit_clk_list;
bit_clk_list->front_porches =
kcalloc(count, sizeof(u32), GFP_KERNEL);
if (!bit_clk_list->front_porches) {
DSI_ERR("failed to allocate space for front porch list\n");
rc = -ENOMEM;
goto error;
}
bit_clk_list->rates =
kcalloc(count, sizeof(u32), GFP_KERNEL);
if (!bit_clk_list->rates) {
DSI_ERR("failed to allocate space for rates list\n");
rc = -ENOMEM;
goto error;
}
memcpy(bit_clk_list->rates, src->priv_info->bit_clk_list.rates,
count*sizeof(u32));
bit_clk_list->pixel_clks_khz =
kcalloc(count, sizeof(u32), GFP_KERNEL);
if (!bit_clk_list->pixel_clks_khz) {
DSI_ERR("failed to allocate space for pixel clocks list\n");
rc = -ENOMEM;
goto error;
}
return rc;
error:
kfree(bit_clk_list->rates);
kfree(bit_clk_list->front_porches);
kfree(bit_clk_list->pixel_clks_khz);
return rc;
}
int dsi_display_restore_bit_clk(struct dsi_display *display, struct dsi_display_mode *mode)
{
int i;
@@ -6806,6 +6919,10 @@ int dsi_display_restore_bit_clk(struct dsi_display *display, struct dsi_display_
return -EINVAL;
}
/* avoid updating bit_clk for dyn clk feature disbaled usecase */
if (!display->panel->dyn_clk_caps.dyn_clk_support)
return 0;
clk_rate_hz = display->cached_clk_rate;
if (mode->priv_info->bit_clk_list.count) {
@@ -6891,6 +7008,7 @@ int dsi_display_get_modes(struct dsi_display *display,
int topology_override = NO_OVERRIDE;
bool is_preferred = false;
u32 frame_threshold_us = ctrl->ctrl->frame_threshold_time_us;
struct msm_dyn_clk_list *bit_clk_list;
memset(&display_mode, 0, sizeof(display_mode));
@@ -6984,10 +7102,24 @@ int dsi_display_get_modes(struct dsi_display *display,
* Qsync min fps for the mode will be populated in the timing info
* in dsi_panel_get_mode function.
*/
sub_mode->priv_info->qsync_min_fps = sub_mode->timing.qsync_min_fps;
display_mode.priv_info->qsync_min_fps = sub_mode->timing.qsync_min_fps;
if (!dfps_caps.dfps_support || !support_video_mode)
continue;
sub_mode->priv_info = kmemdup(display_mode.priv_info,
sizeof(*sub_mode->priv_info), GFP_KERNEL);
if (!sub_mode->priv_info) {
rc = -ENOMEM;
goto error;
}
rc = dsi_display_mode_dyn_clk_cpy(display,
&display_mode, sub_mode);
if (rc) {
DSI_ERR("unable to copy dyn clock list\n");
goto error;
}
sub_mode->mode_idx += (array_idx - 1);
curr_refresh_rate = sub_mode->timing.refresh_rate;
sub_mode->timing.refresh_rate = dfps_caps.dfps_list[i];
@@ -7010,6 +7142,17 @@ int dsi_display_get_modes(struct dsi_display *display,
/* Set first timing sub mode as preferred mode */
display->modes[start].is_preferred = true;
}
bit_clk_list = &display_mode.priv_info->bit_clk_list;
if (support_video_mode && dfps_caps.dfps_support) {
if (dyn_clk_caps->dyn_clk_support) {
kfree(bit_clk_list->rates);
kfree(bit_clk_list->front_porches);
kfree(bit_clk_list->pixel_clks_khz);
}
kfree(display_mode.priv_info);
}
}
if (dsc_modes && nondsc_modes)
@@ -7206,7 +7349,8 @@ int dsi_display_find_mode(struct dsi_display *display,
return rc;
}
priv_info = kzalloc(sizeof(struct dsi_display_mode_priv_info), GFP_KERNEL);
priv_info = kvzalloc(sizeof(struct dsi_display_mode_priv_info),
GFP_KERNEL);
if (ZERO_OR_NULL_PTR(priv_info))
return -ENOMEM;
@@ -7241,7 +7385,7 @@ int dsi_display_find_mode(struct dsi_display *display,
cmp->priv_info = NULL;
mutex_unlock(&display->display_lock);
kfree(priv_info);
kvfree(priv_info);
if (!*out_mode) {
DSI_ERR("[%s] failed to find mode for v_active %u h_active %u fps %u pclk %u\n",