disp: msm: use connector properties to expose and set panel mode
Expose panel mode from kernel to SDM with SDE connector property CONNECTOR_PROP_MODE_INFO and set panel mode from SDM to kernel with SDE connector property CONNECTOR_PROP_SET_PANEL_MODE for avoiding private change in upstream code in QGKI kernel. Change-Id: I0629dad9399967cc1118ac02ce30597076ca367d Signed-off-by: Lei Chen <chenlei@codeaurora.org>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SDE_DRM_H_
|
#ifndef _SDE_DRM_H_
|
||||||
@@ -692,6 +692,13 @@ struct drm_msm_display_hint {
|
|||||||
#define DRM_EVENT_LTM_WB_PB 0X80000009
|
#define DRM_EVENT_LTM_WB_PB 0X80000009
|
||||||
#define DRM_EVENT_LTM_OFF 0X8000000A
|
#define DRM_EVENT_LTM_OFF 0X8000000A
|
||||||
|
|
||||||
|
#ifndef DRM_MODE_FLAG_VID_MODE_PANEL
|
||||||
|
#define DRM_MODE_FLAG_VID_MODE_PANEL 0x01
|
||||||
|
#endif
|
||||||
|
#ifndef DRM_MODE_FLAG_CMD_MODE_PANEL
|
||||||
|
#define DRM_MODE_FLAG_CMD_MODE_PANEL 0x02
|
||||||
|
#endif
|
||||||
|
|
||||||
/* display hint flags*/
|
/* display hint flags*/
|
||||||
#define DRM_MSM_DISPLAY_EARLY_WAKEUP_HINT 0x01
|
#define DRM_MSM_DISPLAY_EARLY_WAKEUP_HINT 0x01
|
||||||
#define DRM_MSM_DISPLAY_POWER_COLLAPSE_HINT 0x02
|
#define DRM_MSM_DISPLAY_POWER_COLLAPSE_HINT 0x02
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
@@ -457,6 +457,7 @@ int dp_connector_get_info(struct drm_connector *connector,
|
|||||||
info->num_of_h_tiles = 1;
|
info->num_of_h_tiles = 1;
|
||||||
info->h_tile_instance[0] = 0;
|
info->h_tile_instance[0] = 0;
|
||||||
info->is_connected = display->is_sst_connected;
|
info->is_connected = display->is_sst_connected;
|
||||||
|
info->curr_panel_mode = MSM_DISPLAY_VIDEO_MODE;
|
||||||
info->capabilities = MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID |
|
info->capabilities = MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID |
|
||||||
MSM_DISPLAY_CAP_HOT_PLUG;
|
MSM_DISPLAY_CAP_HOT_PLUG;
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _DSI_DEFS_H_
|
#ifndef _DSI_DEFS_H_
|
||||||
@@ -59,9 +59,9 @@ enum dsi_pixel_format {
|
|||||||
* @DSI_OP_MODE_MAX:
|
* @DSI_OP_MODE_MAX:
|
||||||
*/
|
*/
|
||||||
enum dsi_op_mode {
|
enum dsi_op_mode {
|
||||||
DSI_OP_VIDEO_MODE = 0,
|
DSI_OP_VIDEO_MODE = BIT(0),
|
||||||
DSI_OP_CMD_MODE,
|
DSI_OP_CMD_MODE = BIT(1),
|
||||||
DSI_OP_MODE_MAX
|
DSI_OP_MODE_MAX = BIT(2),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,10 +72,12 @@ enum dsi_op_mode {
|
|||||||
* @DSI_MODE_FLAG_DMS: Seamless transition is dynamic mode switch
|
* @DSI_MODE_FLAG_DMS: Seamless transition is dynamic mode switch
|
||||||
* @DSI_MODE_FLAG_VRR: Seamless transition is DynamicFPS.
|
* @DSI_MODE_FLAG_VRR: Seamless transition is DynamicFPS.
|
||||||
* New timing values are sent from DAL.
|
* New timing values are sent from DAL.
|
||||||
* @DSI_MODE_FLAG_POMS:
|
|
||||||
* Seamless transition is dynamic panel operating mode switch
|
|
||||||
* @DSI_MODE_FLAG_DYN_CLK: Seamless transition is dynamic clock change
|
* @DSI_MODE_FLAG_DYN_CLK: Seamless transition is dynamic clock change
|
||||||
* @DSI_MODE_FLAG_DMS_FPS: Seamless fps only transition in Dynamic Mode Switch
|
* @DSI_MODE_FLAG_DMS_FPS: Seamless fps only transition in Dynamic Mode Switch
|
||||||
|
* @DSI_MODE_FLAG_POMS_TO_VID:
|
||||||
|
* Seamless transition is dynamic panel operating mode switch to video
|
||||||
|
* @DSI_MODE_FLAG_POMS_TO_CMD:
|
||||||
|
* Seamless transition is dynamic panel operating mode switch to cmd
|
||||||
*/
|
*/
|
||||||
enum dsi_mode_flags {
|
enum dsi_mode_flags {
|
||||||
DSI_MODE_FLAG_SEAMLESS = BIT(0),
|
DSI_MODE_FLAG_SEAMLESS = BIT(0),
|
||||||
@@ -83,9 +85,10 @@ enum dsi_mode_flags {
|
|||||||
DSI_MODE_FLAG_VBLANK_PRE_MODESET = BIT(2),
|
DSI_MODE_FLAG_VBLANK_PRE_MODESET = BIT(2),
|
||||||
DSI_MODE_FLAG_DMS = BIT(3),
|
DSI_MODE_FLAG_DMS = BIT(3),
|
||||||
DSI_MODE_FLAG_VRR = BIT(4),
|
DSI_MODE_FLAG_VRR = BIT(4),
|
||||||
DSI_MODE_FLAG_POMS = BIT(5),
|
DSI_MODE_FLAG_DYN_CLK = BIT(5),
|
||||||
DSI_MODE_FLAG_DYN_CLK = BIT(6),
|
DSI_MODE_FLAG_DMS_FPS = BIT(6),
|
||||||
DSI_MODE_FLAG_DMS_FPS = BIT(7),
|
DSI_MODE_FLAG_POMS_TO_VID = BIT(7),
|
||||||
|
DSI_MODE_FLAG_POMS_TO_CMD = BIT(8)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -629,7 +632,7 @@ struct dsi_display_mode_priv_info {
|
|||||||
* @timing: Timing parameters for the panel.
|
* @timing: Timing parameters for the panel.
|
||||||
* @pixel_clk_khz: Pixel clock in Khz.
|
* @pixel_clk_khz: Pixel clock in Khz.
|
||||||
* @dsi_mode_flags: Flags to signal other drm components via private flags
|
* @dsi_mode_flags: Flags to signal other drm components via private flags
|
||||||
* @panel_mode: Panel mode
|
* @panel_mode_caps: panel mode capabilities.
|
||||||
* @is_preferred: Is mode preferred
|
* @is_preferred: Is mode preferred
|
||||||
* @priv_info: Mode private info
|
* @priv_info: Mode private info
|
||||||
*/
|
*/
|
||||||
@@ -637,7 +640,7 @@ struct dsi_display_mode {
|
|||||||
struct dsi_mode_info timing;
|
struct dsi_mode_info timing;
|
||||||
u32 pixel_clk_khz;
|
u32 pixel_clk_khz;
|
||||||
u32 dsi_mode_flags;
|
u32 dsi_mode_flags;
|
||||||
enum dsi_op_mode panel_mode;
|
u32 panel_mode_caps;
|
||||||
bool is_preferred;
|
bool is_preferred;
|
||||||
struct dsi_display_mode_priv_info *priv_info;
|
struct dsi_display_mode_priv_info *priv_info;
|
||||||
};
|
};
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
@@ -5001,9 +5001,13 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDE_EVT32(mode->dsi_mode_flags, mode->panel_mode);
|
SDE_EVT32(mode->dsi_mode_flags, display->panel->panel_mode);
|
||||||
|
|
||||||
|
if (mode->dsi_mode_flags & DSI_MODE_FLAG_POMS_TO_VID)
|
||||||
|
display->panel->panel_mode = DSI_OP_VIDEO_MODE;
|
||||||
|
else if (mode->dsi_mode_flags & DSI_MODE_FLAG_POMS_TO_CMD)
|
||||||
|
display->panel->panel_mode = DSI_OP_CMD_MODE;
|
||||||
|
|
||||||
display->panel->panel_mode = mode->panel_mode;
|
|
||||||
rc = dsi_panel_get_host_cfg_for_mode(display->panel,
|
rc = dsi_panel_get_host_cfg_for_mode(display->panel,
|
||||||
mode,
|
mode,
|
||||||
&display->config);
|
&display->config);
|
||||||
@@ -6602,7 +6606,7 @@ void dsi_display_adjust_mode_timing(struct dsi_display *display,
|
|||||||
dyn_clk_caps = &(display->panel->dyn_clk_caps);
|
dyn_clk_caps = &(display->panel->dyn_clk_caps);
|
||||||
|
|
||||||
/* Constant FPS is not supported on command mode */
|
/* Constant FPS is not supported on command mode */
|
||||||
if (dsi_mode->panel_mode == DSI_OP_CMD_MODE)
|
if (!(dsi_mode->panel_mode_caps & DSI_OP_VIDEO_MODE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!dyn_clk_caps->maintain_const_fps)
|
if (!dyn_clk_caps->maintain_const_fps)
|
||||||
@@ -6728,7 +6732,7 @@ static void _dsi_display_populate_bit_clks(struct dsi_display *display,
|
|||||||
|
|
||||||
dsi_display_adjust_mode_timing(display, dst, lanes,
|
dsi_display_adjust_mode_timing(display, dst, lanes,
|
||||||
bpp);
|
bpp);
|
||||||
|
dst->panel_mode_caps = DSI_OP_VIDEO_MODE;
|
||||||
dst->pixel_clk_khz =
|
dst->pixel_clk_khz =
|
||||||
div_u64(dst->timing.clk_rate_hz * lanes, bpp);
|
div_u64(dst->timing.clk_rate_hz * lanes, bpp);
|
||||||
dst->pixel_clk_khz /= 1000;
|
dst->pixel_clk_khz /= 1000;
|
||||||
@@ -6750,7 +6754,7 @@ int dsi_display_get_modes(struct dsi_display *display,
|
|||||||
struct dsi_dfps_capabilities dfps_caps;
|
struct dsi_dfps_capabilities dfps_caps;
|
||||||
struct dsi_display_ctrl *ctrl;
|
struct dsi_display_ctrl *ctrl;
|
||||||
struct dsi_host_common_cfg *host = &display->panel->host_config;
|
struct dsi_host_common_cfg *host = &display->panel->host_config;
|
||||||
bool is_split_link, is_cmd_mode;
|
bool is_split_link, support_cmd_mode, support_video_mode;
|
||||||
u32 num_dfps_rates, timing_mode_count, display_mode_count;
|
u32 num_dfps_rates, timing_mode_count, display_mode_count;
|
||||||
u32 sublinks_count, mode_idx, array_idx = 0;
|
u32 sublinks_count, mode_idx, array_idx = 0;
|
||||||
struct dsi_dyn_clk_caps *dyn_clk_caps;
|
struct dsi_dyn_clk_caps *dyn_clk_caps;
|
||||||
@@ -6816,16 +6820,17 @@ int dsi_display_get_modes(struct dsi_display *display,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_cmd_mode = (display_mode.panel_mode == DSI_OP_CMD_MODE);
|
support_cmd_mode = display_mode.panel_mode_caps & DSI_OP_CMD_MODE;
|
||||||
|
support_video_mode = display_mode.panel_mode_caps & DSI_OP_VIDEO_MODE;
|
||||||
|
|
||||||
/* Setup widebus support */
|
/* Setup widebus support */
|
||||||
display_mode.priv_info->widebus_support =
|
display_mode.priv_info->widebus_support =
|
||||||
ctrl->ctrl->hw.widebus_support;
|
ctrl->ctrl->hw.widebus_support;
|
||||||
num_dfps_rates = ((!dfps_caps.dfps_support ||
|
num_dfps_rates = ((!dfps_caps.dfps_support ||
|
||||||
is_cmd_mode) ? 1 : dfps_caps.dfps_list_len);
|
!support_video_mode) ? 1 : dfps_caps.dfps_list_len);
|
||||||
|
|
||||||
/* Calculate dsi frame transfer time */
|
/* Calculate dsi frame transfer time */
|
||||||
if (is_cmd_mode) {
|
if (support_cmd_mode) {
|
||||||
dsi_panel_calc_dsi_transfer_time(
|
dsi_panel_calc_dsi_transfer_time(
|
||||||
&display->panel->host_config,
|
&display->panel->host_config,
|
||||||
&display_mode, frame_threshold_us);
|
&display_mode, frame_threshold_us);
|
||||||
@@ -6874,7 +6879,7 @@ int dsi_display_get_modes(struct dsi_display *display,
|
|||||||
memcpy(sub_mode, &display_mode, sizeof(display_mode));
|
memcpy(sub_mode, &display_mode, sizeof(display_mode));
|
||||||
array_idx++;
|
array_idx++;
|
||||||
|
|
||||||
if (!dfps_caps.dfps_support || is_cmd_mode)
|
if (!dfps_caps.dfps_support || !support_video_mode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
curr_refresh_rate = sub_mode->timing.refresh_rate;
|
curr_refresh_rate = sub_mode->timing.refresh_rate;
|
||||||
@@ -6882,18 +6887,9 @@ int dsi_display_get_modes(struct dsi_display *display,
|
|||||||
|
|
||||||
dsi_display_get_dfps_timing(display, sub_mode,
|
dsi_display_get_dfps_timing(display, sub_mode,
|
||||||
curr_refresh_rate);
|
curr_refresh_rate);
|
||||||
|
sub_mode->panel_mode_caps = DSI_OP_VIDEO_MODE;
|
||||||
}
|
}
|
||||||
end = array_idx;
|
end = array_idx;
|
||||||
/*
|
|
||||||
* if POMS is enabled and boot up mode is video mode,
|
|
||||||
* skip bit clk rates update for command mode,
|
|
||||||
* else if dynamic clk switch is supported then update all
|
|
||||||
* the bit clk rates.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (is_cmd_mode &&
|
|
||||||
(display->panel->panel_mode == DSI_OP_VIDEO_MODE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
_dsi_display_populate_bit_clks(display, start, end, &array_idx);
|
_dsi_display_populate_bit_clks(display, start, end, &array_idx);
|
||||||
if (is_preferred) {
|
if (is_preferred) {
|
||||||
@@ -7045,7 +7041,6 @@ int dsi_display_find_mode(struct dsi_display *display,
|
|||||||
if (cmp->timing.v_active == m->timing.v_active &&
|
if (cmp->timing.v_active == m->timing.v_active &&
|
||||||
cmp->timing.h_active == m->timing.h_active &&
|
cmp->timing.h_active == m->timing.h_active &&
|
||||||
cmp->timing.refresh_rate == m->timing.refresh_rate &&
|
cmp->timing.refresh_rate == m->timing.refresh_rate &&
|
||||||
cmp->panel_mode == m->panel_mode &&
|
|
||||||
cmp->pixel_clk_khz == m->pixel_clk_khz) {
|
cmp->pixel_clk_khz == m->pixel_clk_khz) {
|
||||||
*out_mode = m;
|
*out_mode = m;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@@ -7098,8 +7093,9 @@ int dsi_display_validate_mode_change(struct dsi_display *display,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct dsi_dfps_capabilities dfps_caps;
|
struct dsi_dfps_capabilities dfps_caps;
|
||||||
struct dsi_dyn_clk_caps *dyn_clk_caps;
|
struct dsi_dyn_clk_caps *dyn_clk_caps;
|
||||||
|
struct sde_connector *sde_conn;
|
||||||
|
|
||||||
if (!display || !adj_mode) {
|
if (!display || !adj_mode || !display->drm_conn) {
|
||||||
DSI_ERR("Invalid params\n");
|
DSI_ERR("Invalid params\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -7109,11 +7105,26 @@ int dsi_display_validate_mode_change(struct dsi_display *display,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cur_mode->timing.v_active != adj_mode->timing.v_active) ||
|
||||||
|
(cur_mode->timing.h_active != adj_mode->timing.h_active)) {
|
||||||
|
DSI_DEBUG("Avoid VRR and POMS when resolution is changed\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
sde_conn = to_sde_connector(display->drm_conn);
|
||||||
|
|
||||||
mutex_lock(&display->display_lock);
|
mutex_lock(&display->display_lock);
|
||||||
dyn_clk_caps = &(display->panel->dyn_clk_caps);
|
|
||||||
if ((cur_mode->timing.v_active == adj_mode->timing.v_active) &&
|
if (sde_conn->expected_panel_mode == MSM_DISPLAY_VIDEO_MODE &&
|
||||||
(cur_mode->timing.h_active == adj_mode->timing.h_active) &&
|
display->config.panel_mode == DSI_OP_CMD_MODE) {
|
||||||
(cur_mode->panel_mode == adj_mode->panel_mode)) {
|
adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS_TO_VID;
|
||||||
|
DSI_DEBUG("Panel operating mode change to video detected\n");
|
||||||
|
} else if (sde_conn->expected_panel_mode == MSM_DISPLAY_CMD_MODE &&
|
||||||
|
display->config.panel_mode == DSI_OP_VIDEO_MODE) {
|
||||||
|
adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS_TO_CMD;
|
||||||
|
DSI_DEBUG("Panel operating mode change to command detected\n");
|
||||||
|
} else {
|
||||||
|
dyn_clk_caps = &(display->panel->dyn_clk_caps);
|
||||||
/* dfps and dynamic clock with const fps use case */
|
/* dfps and dynamic clock with const fps use case */
|
||||||
if (dsi_display_mode_switch_dfps(cur_mode, adj_mode)) {
|
if (dsi_display_mode_switch_dfps(cur_mode, adj_mode)) {
|
||||||
dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
|
dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
|
||||||
@@ -7679,7 +7690,7 @@ int dsi_display_prepare(struct dsi_display *display)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) &&
|
if (!display->poms_pending &&
|
||||||
(!is_skip_op_required(display))) {
|
(!is_skip_op_required(display))) {
|
||||||
/*
|
/*
|
||||||
* For continuous splash/trusted vm, we skip panel
|
* For continuous splash/trusted vm, we skip panel
|
||||||
@@ -7772,7 +7783,7 @@ int dsi_display_prepare(struct dsi_display *display)
|
|||||||
goto error_ctrl_link_off;
|
goto error_ctrl_link_off;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mode->dsi_mode_flags & DSI_MODE_FLAG_POMS)) {
|
if (!display->poms_pending) {
|
||||||
rc = dsi_panel_prepare(display->panel);
|
rc = dsi_panel_prepare(display->panel);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DSI_ERR("[%s] panel prepare failed, rc=%d\n",
|
DSI_ERR("[%s] panel prepare failed, rc=%d\n",
|
||||||
@@ -8123,8 +8134,7 @@ int dsi_display_enable(struct dsi_display *display)
|
|||||||
display->name, rc);
|
display->name, rc);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else if (!(display->panel->cur_mode->dsi_mode_flags &
|
} else if (!display->poms_pending) {
|
||||||
DSI_MODE_FLAG_POMS)){
|
|
||||||
rc = dsi_panel_enable(display->panel);
|
rc = dsi_panel_enable(display->panel);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DSI_ERR("[%s] failed to enable DSI panel, rc=%d\n",
|
DSI_ERR("[%s] failed to enable DSI panel, rc=%d\n",
|
||||||
@@ -8197,13 +8207,13 @@ int dsi_display_post_enable(struct dsi_display *display)
|
|||||||
|
|
||||||
mutex_lock(&display->display_lock);
|
mutex_lock(&display->display_lock);
|
||||||
|
|
||||||
if (display->panel->cur_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) {
|
if (display->panel->cur_mode->dsi_mode_flags &
|
||||||
if (display->config.panel_mode == DSI_OP_CMD_MODE)
|
DSI_MODE_FLAG_POMS_TO_CMD) {
|
||||||
dsi_panel_mode_switch_to_cmd(display->panel);
|
dsi_panel_mode_switch_to_cmd(display->panel);
|
||||||
|
} else if (display->panel->cur_mode->dsi_mode_flags &
|
||||||
if (display->config.panel_mode == DSI_OP_VIDEO_MODE)
|
DSI_MODE_FLAG_POMS_TO_VID)
|
||||||
dsi_panel_mode_switch_to_vid(display->panel);
|
dsi_panel_mode_switch_to_vid(display->panel);
|
||||||
} else {
|
else {
|
||||||
rc = dsi_panel_post_enable(display->panel);
|
rc = dsi_panel_post_enable(display->panel);
|
||||||
if (rc)
|
if (rc)
|
||||||
DSI_ERR("[%s] panel post-enable failed, rc=%d\n",
|
DSI_ERR("[%s] panel post-enable failed, rc=%d\n",
|
||||||
|
@@ -59,11 +59,6 @@ static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode,
|
|||||||
!!(drm_mode->flags & DRM_MODE_FLAG_PHSYNC);
|
!!(drm_mode->flags & DRM_MODE_FLAG_PHSYNC);
|
||||||
dsi_mode->timing.v_sync_polarity =
|
dsi_mode->timing.v_sync_polarity =
|
||||||
!!(drm_mode->flags & DRM_MODE_FLAG_PVSYNC);
|
!!(drm_mode->flags & DRM_MODE_FLAG_PVSYNC);
|
||||||
|
|
||||||
if (drm_mode->flags & DRM_MODE_FLAG_VID_MODE_PANEL)
|
|
||||||
dsi_mode->panel_mode = DSI_OP_VIDEO_MODE;
|
|
||||||
if (drm_mode->flags & DRM_MODE_FLAG_CMD_MODE_PANEL)
|
|
||||||
dsi_mode->panel_mode = DSI_OP_CMD_MODE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msm_parse_mode_priv_info(const struct msm_display_mode *msm_mode,
|
static void msm_parse_mode_priv_info(const struct msm_display_mode *msm_mode,
|
||||||
@@ -90,8 +85,10 @@ static void msm_parse_mode_priv_info(const struct msm_display_mode *msm_mode,
|
|||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
|
||||||
if (msm_is_mode_seamless_vrr(msm_mode))
|
if (msm_is_mode_seamless_vrr(msm_mode))
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
|
||||||
if (msm_is_mode_seamless_poms(msm_mode))
|
if (msm_is_mode_seamless_poms_to_vid(msm_mode))
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS;
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS_TO_VID;
|
||||||
|
if (msm_is_mode_seamless_poms_to_cmd(msm_mode))
|
||||||
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS_TO_CMD;
|
||||||
if (msm_is_mode_seamless_dyn_clk(msm_mode))
|
if (msm_is_mode_seamless_dyn_clk(msm_mode))
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DYN_CLK;
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DYN_CLK;
|
||||||
}
|
}
|
||||||
@@ -99,7 +96,15 @@ static void msm_parse_mode_priv_info(const struct msm_display_mode *msm_mode,
|
|||||||
void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
|
void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
|
||||||
struct drm_display_mode *drm_mode)
|
struct drm_display_mode *drm_mode)
|
||||||
{
|
{
|
||||||
bool video_mode = (dsi_mode->panel_mode == DSI_OP_VIDEO_MODE);
|
char *panel_caps = "vid";
|
||||||
|
|
||||||
|
if ((dsi_mode->panel_mode_caps & DSI_OP_VIDEO_MODE) &&
|
||||||
|
(dsi_mode->panel_mode_caps & DSI_OP_CMD_MODE))
|
||||||
|
panel_caps = "vid_cmd";
|
||||||
|
else if (dsi_mode->panel_mode_caps & DSI_OP_VIDEO_MODE)
|
||||||
|
panel_caps = "vid";
|
||||||
|
else if (dsi_mode->panel_mode_caps & DSI_OP_CMD_MODE)
|
||||||
|
panel_caps = "cmd";
|
||||||
|
|
||||||
memset(drm_mode, 0, sizeof(*drm_mode));
|
memset(drm_mode, 0, sizeof(*drm_mode));
|
||||||
|
|
||||||
@@ -126,16 +131,11 @@ void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
|
|||||||
if (dsi_mode->timing.v_sync_polarity)
|
if (dsi_mode->timing.v_sync_polarity)
|
||||||
drm_mode->flags |= DRM_MODE_FLAG_PVSYNC;
|
drm_mode->flags |= DRM_MODE_FLAG_PVSYNC;
|
||||||
|
|
||||||
if (dsi_mode->panel_mode == DSI_OP_VIDEO_MODE)
|
|
||||||
drm_mode->flags |= DRM_MODE_FLAG_VID_MODE_PANEL;
|
|
||||||
if (dsi_mode->panel_mode == DSI_OP_CMD_MODE)
|
|
||||||
drm_mode->flags |= DRM_MODE_FLAG_CMD_MODE_PANEL;
|
|
||||||
|
|
||||||
/* set mode name */
|
/* set mode name */
|
||||||
snprintf(drm_mode->name, DRM_DISPLAY_MODE_LEN, "%dx%dx%dx%d%s",
|
snprintf(drm_mode->name, DRM_DISPLAY_MODE_LEN, "%dx%dx%dx%d%s",
|
||||||
drm_mode->hdisplay, drm_mode->vdisplay,
|
drm_mode->hdisplay, drm_mode->vdisplay,
|
||||||
drm_mode->vrefresh, drm_mode->clock,
|
drm_mode->vrefresh, drm_mode->clock,
|
||||||
video_mode ? "vid" : "cmd");
|
panel_caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dsi_convert_to_msm_mode(const struct dsi_display_mode *dsi_mode,
|
static void dsi_convert_to_msm_mode(const struct dsi_display_mode *dsi_mode,
|
||||||
@@ -154,8 +154,10 @@ static void dsi_convert_to_msm_mode(const struct dsi_display_mode *dsi_mode,
|
|||||||
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS;
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS;
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR)
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR)
|
||||||
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR;
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR;
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS)
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS_TO_VID)
|
||||||
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_POMS;
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_POMS_VID;
|
||||||
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS_TO_CMD)
|
||||||
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_POMS_CMD;
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK)
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK)
|
||||||
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYN_CLK;
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYN_CLK;
|
||||||
}
|
}
|
||||||
@@ -263,9 +265,11 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
|
|||||||
|
|
||||||
if (display && display->drm_conn) {
|
if (display && display->drm_conn) {
|
||||||
sde_connector_helper_bridge_enable(display->drm_conn);
|
sde_connector_helper_bridge_enable(display->drm_conn);
|
||||||
if (c_bridge->dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS)
|
if (display->poms_pending) {
|
||||||
|
display->poms_pending = false;
|
||||||
sde_connector_schedule_status_work(display->drm_conn,
|
sde_connector_schedule_status_work(display->drm_conn,
|
||||||
true);
|
true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,6 +433,7 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
|||||||
/* propagate the private info to the adjusted_mode derived dsi mode */
|
/* propagate the private info to the adjusted_mode derived dsi mode */
|
||||||
dsi_mode.priv_info = panel_dsi_mode->priv_info;
|
dsi_mode.priv_info = panel_dsi_mode->priv_info;
|
||||||
dsi_mode.dsi_mode_flags = panel_dsi_mode->dsi_mode_flags;
|
dsi_mode.dsi_mode_flags = panel_dsi_mode->dsi_mode_flags;
|
||||||
|
dsi_mode.panel_mode_caps = panel_dsi_mode->panel_mode_caps;
|
||||||
dsi_mode.timing.dsc_enabled = dsi_mode.priv_info->dsc_enabled;
|
dsi_mode.timing.dsc_enabled = dsi_mode.priv_info->dsc_enabled;
|
||||||
dsi_mode.timing.dsc = &dsi_mode.priv_info->dsc;
|
dsi_mode.timing.dsc = &dsi_mode.priv_info->dsc;
|
||||||
|
|
||||||
@@ -455,25 +460,12 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No panel mode switch when drm pipeline is changing */
|
|
||||||
if ((dsi_mode.panel_mode != cur_dsi_mode.panel_mode) &&
|
|
||||||
(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR)) &&
|
|
||||||
(crtc_state->enable ==
|
|
||||||
crtc_state->crtc->state->enable)) {
|
|
||||||
dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_POMS;
|
|
||||||
|
|
||||||
SDE_EVT32(SDE_EVTLOG_FUNC_CASE1,
|
|
||||||
dsi_mode.timing.h_active,
|
|
||||||
dsi_mode.timing.v_active,
|
|
||||||
dsi_mode.timing.refresh_rate,
|
|
||||||
dsi_mode.pixel_clk_khz,
|
|
||||||
dsi_mode.panel_mode);
|
|
||||||
}
|
|
||||||
/* No DMS/VRR when drm pipeline is changing */
|
/* No DMS/VRR when drm pipeline is changing */
|
||||||
if (!drm_mode_equal(cur_mode, adjusted_mode) &&
|
if (!drm_mode_equal(cur_mode, adjusted_mode) &&
|
||||||
(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR)) &&
|
(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR)) &&
|
||||||
(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS)) &&
|
|
||||||
(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK)) &&
|
(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK)) &&
|
||||||
|
(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS_TO_VID)) &&
|
||||||
|
(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS_TO_CMD)) &&
|
||||||
(!crtc_state->active_changed ||
|
(!crtc_state->active_changed ||
|
||||||
display->is_cont_splash_enabled)) {
|
display->is_cont_splash_enabled)) {
|
||||||
dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS;
|
dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS;
|
||||||
@@ -483,15 +475,16 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
|||||||
dsi_mode.timing.v_active,
|
dsi_mode.timing.v_active,
|
||||||
dsi_mode.timing.refresh_rate,
|
dsi_mode.timing.refresh_rate,
|
||||||
dsi_mode.pixel_clk_khz,
|
dsi_mode.pixel_clk_khz,
|
||||||
dsi_mode.panel_mode);
|
dsi_mode.panel_mode_caps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reject seamless transition when active changed */
|
/* Reject seamless transition when active changed */
|
||||||
if (crtc_state->active_changed &&
|
if (crtc_state->active_changed &&
|
||||||
((dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR) ||
|
((dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR) ||
|
||||||
(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS) ||
|
(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK) ||
|
||||||
(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK))) {
|
(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS_TO_VID) ||
|
||||||
|
(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS_TO_CMD))) {
|
||||||
DSI_INFO("seamless upon active changed 0x%x %d\n",
|
DSI_INFO("seamless upon active changed 0x%x %d\n",
|
||||||
dsi_mode.dsi_mode_flags, crtc_state->active_changed);
|
dsi_mode.dsi_mode_flags, crtc_state->active_changed);
|
||||||
return false;
|
return false;
|
||||||
@@ -579,6 +572,7 @@ int dsi_conn_get_mode_info(struct drm_connector *connector,
|
|||||||
mode_info->jitter_denom = dsi_mode->priv_info->panel_jitter_denom;
|
mode_info->jitter_denom = dsi_mode->priv_info->panel_jitter_denom;
|
||||||
mode_info->dfps_maxfps = dsi_drm_get_dfps_maxfps(display);
|
mode_info->dfps_maxfps = dsi_drm_get_dfps_maxfps(display);
|
||||||
mode_info->clk_rate = dsi_drm_find_bit_clk_rate(display, drm_mode);
|
mode_info->clk_rate = dsi_drm_find_bit_clk_rate(display, drm_mode);
|
||||||
|
mode_info->panel_mode_caps = dsi_mode->panel_mode_caps;
|
||||||
mode_info->mdp_transfer_time_us =
|
mode_info->mdp_transfer_time_us =
|
||||||
dsi_mode->priv_info->mdp_transfer_time_us;
|
dsi_mode->priv_info->mdp_transfer_time_us;
|
||||||
|
|
||||||
@@ -1210,6 +1204,7 @@ void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector,
|
|||||||
void *display)
|
void *display)
|
||||||
{
|
{
|
||||||
u32 mode_idx = 0, cmp_mode_idx = 0;
|
u32 mode_idx = 0, cmp_mode_idx = 0;
|
||||||
|
u32 common_mode_caps = 0;
|
||||||
struct drm_display_mode *drm_mode, *cmp_drm_mode;
|
struct drm_display_mode *drm_mode, *cmp_drm_mode;
|
||||||
struct dsi_display_mode dsi_mode, *panel_dsi_mode, *cmp_panel_dsi_mode;
|
struct dsi_display_mode dsi_mode, *panel_dsi_mode, *cmp_panel_dsi_mode;
|
||||||
struct list_head *mode_list = &connector->modes;
|
struct list_head *mode_list = &connector->modes;
|
||||||
@@ -1255,6 +1250,8 @@ void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector,
|
|||||||
|
|
||||||
cmp_dsi_mode_info = cmp_panel_dsi_mode->priv_info;
|
cmp_dsi_mode_info = cmp_panel_dsi_mode->priv_info;
|
||||||
allow_switch = false;
|
allow_switch = false;
|
||||||
|
common_mode_caps = (panel_dsi_mode->panel_mode_caps &
|
||||||
|
cmp_panel_dsi_mode->panel_mode_caps);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FPS switch among video modes, is only supported
|
* FPS switch among video modes, is only supported
|
||||||
@@ -1262,14 +1259,12 @@ void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector,
|
|||||||
* Reject any mode switches between video mode timing
|
* Reject any mode switches between video mode timing
|
||||||
* nodes if support for those features is not present.
|
* nodes if support for those features is not present.
|
||||||
*/
|
*/
|
||||||
if (panel_dsi_mode->panel_mode ==
|
if (common_mode_caps & DSI_OP_CMD_MODE) {
|
||||||
cmp_panel_dsi_mode->panel_mode) {
|
allow_switch = true;
|
||||||
if (panel_dsi_mode->panel_mode ==
|
} else if ((common_mode_caps & DSI_OP_VIDEO_MODE) &&
|
||||||
DSI_OP_CMD_MODE)
|
(panel->dfps_caps.dfps_support ||
|
||||||
allow_switch = true;
|
panel->dyn_clk_caps.dyn_clk_support)) {
|
||||||
else if (panel->dfps_caps.dfps_support ||
|
allow_switch = true;
|
||||||
panel->dyn_clk_caps.dyn_clk_support)
|
|
||||||
allow_switch = true;
|
|
||||||
} else {
|
} else {
|
||||||
if (is_valid_poms_switch(panel_dsi_mode,
|
if (is_valid_poms_switch(panel_dsi_mode,
|
||||||
cmp_panel_dsi_mode))
|
cmp_panel_dsi_mode))
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@@ -2481,7 +2481,7 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode,
|
|||||||
priv_info->phy_timing_len = len;
|
priv_info->phy_timing_len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode->panel_mode == DSI_OP_VIDEO_MODE) {
|
if (mode->panel_mode_caps & DSI_OP_VIDEO_MODE) {
|
||||||
/*
|
/*
|
||||||
* For command mode we update the pclk as part of
|
* For command mode we update the pclk as part of
|
||||||
* function dsi_panel_calc_dsi_transfer_time( )
|
* function dsi_panel_calc_dsi_transfer_time( )
|
||||||
@@ -2677,7 +2677,7 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int dsi_panel_parse_vdc_params(struct dsi_display_mode *mode,
|
static int dsi_panel_parse_vdc_params(struct dsi_display_mode *mode,
|
||||||
struct dsi_parser_utils *utils, int traffic_mode, int panel_mode)
|
struct dsi_parser_utils *utils, int traffic_mode)
|
||||||
{
|
{
|
||||||
u32 data;
|
u32 data;
|
||||||
int rc = -EINVAL;
|
int rc = -EINVAL;
|
||||||
@@ -2701,7 +2701,6 @@ static int dsi_panel_parse_vdc_params(struct dsi_display_mode *mode,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv_info->vdc.panel_mode = panel_mode;
|
|
||||||
priv_info->vdc.traffic_mode = traffic_mode;
|
priv_info->vdc.traffic_mode = traffic_mode;
|
||||||
|
|
||||||
rc = utils->read_u32(utils->data, "qcom,vdc-version", &data);
|
rc = utils->read_u32(utils->data, "qcom,vdc-version", &data);
|
||||||
@@ -3090,33 +3089,26 @@ static int dsi_panel_parse_partial_update_caps(struct dsi_display_mode *mode,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsi_panel_parse_panel_mode_caps(struct dsi_display_mode *mode,
|
static bool dsi_panel_parse_panel_mode_caps(struct dsi_display_mode *mode,
|
||||||
struct dsi_parser_utils *utils)
|
struct dsi_parser_utils *utils)
|
||||||
{
|
{
|
||||||
bool vid_mode_support, cmd_mode_support;
|
|
||||||
|
|
||||||
if (!mode || !mode->priv_info) {
|
if (!mode || !mode->priv_info) {
|
||||||
DSI_ERR("invalid arguments\n");
|
DSI_ERR("invalid arguments\n");
|
||||||
return -EINVAL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vid_mode_support = utils->read_bool(utils->data,
|
if (utils->read_bool(utils->data, "qcom,mdss-dsi-video-mode"))
|
||||||
"qcom,mdss-dsi-video-mode");
|
mode->panel_mode_caps |= DSI_OP_VIDEO_MODE;
|
||||||
|
|
||||||
cmd_mode_support = utils->read_bool(utils->data,
|
if (utils->read_bool(utils->data, "qcom,mdss-dsi-cmd-mode"))
|
||||||
"qcom,mdss-dsi-cmd-mode");
|
mode->panel_mode_caps |= DSI_OP_CMD_MODE;
|
||||||
|
|
||||||
if (cmd_mode_support)
|
if (!mode->panel_mode_caps)
|
||||||
mode->panel_mode = DSI_OP_CMD_MODE;
|
return false;
|
||||||
else if (vid_mode_support)
|
|
||||||
mode->panel_mode = DSI_OP_VIDEO_MODE;
|
|
||||||
else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int dsi_panel_parse_dms_info(struct dsi_panel *panel)
|
static int dsi_panel_parse_dms_info(struct dsi_panel *panel)
|
||||||
{
|
{
|
||||||
int dms_enabled;
|
int dms_enabled;
|
||||||
@@ -3980,7 +3972,6 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
|
|||||||
u32 child_idx = 0;
|
u32 child_idx = 0;
|
||||||
int rc = 0, num_timings;
|
int rc = 0, num_timings;
|
||||||
int traffic_mode;
|
int traffic_mode;
|
||||||
int panel_mode;
|
|
||||||
void *utils_data = NULL;
|
void *utils_data = NULL;
|
||||||
|
|
||||||
if (!panel || !mode) {
|
if (!panel || !mode) {
|
||||||
@@ -4016,7 +4007,6 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
|
|||||||
|
|
||||||
utils_data = utils->data;
|
utils_data = utils->data;
|
||||||
traffic_mode = panel->video_config.traffic_mode;
|
traffic_mode = panel->video_config.traffic_mode;
|
||||||
panel_mode = panel->panel_mode;
|
|
||||||
|
|
||||||
dsi_for_each_child_node(timings_np, child_np) {
|
dsi_for_each_child_node(timings_np, child_np) {
|
||||||
if (index != child_idx++)
|
if (index != child_idx++)
|
||||||
@@ -4024,6 +4014,16 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
|
|||||||
|
|
||||||
utils->data = child_np;
|
utils->data = child_np;
|
||||||
|
|
||||||
|
if (panel->panel_mode_switch_enabled) {
|
||||||
|
if (!dsi_panel_parse_panel_mode_caps(mode, utils)) {
|
||||||
|
mode->panel_mode_caps = panel->panel_mode;
|
||||||
|
DSI_INFO("panel mode isn't specified in timing[%d]\n",
|
||||||
|
child_idx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mode->panel_mode_caps = panel->panel_mode;
|
||||||
|
}
|
||||||
|
|
||||||
rc = dsi_panel_parse_timing(&mode->timing, utils);
|
rc = dsi_panel_parse_timing(&mode->timing, utils);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DSI_ERR("failed to parse panel timing, rc=%d\n", rc);
|
DSI_ERR("failed to parse panel timing, rc=%d\n", rc);
|
||||||
@@ -4036,8 +4036,7 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
|
|||||||
goto parse_fail;
|
goto parse_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = dsi_panel_parse_vdc_params(mode, utils, traffic_mode,
|
rc = dsi_panel_parse_vdc_params(mode, utils, traffic_mode);
|
||||||
panel_mode);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DSI_ERR("failed to parse vdc params, rc=%d\n", rc);
|
DSI_ERR("failed to parse vdc params, rc=%d\n", rc);
|
||||||
goto parse_fail;
|
goto parse_fail;
|
||||||
@@ -4071,19 +4070,6 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
|
|||||||
rc = dsi_panel_parse_partial_update_caps(mode, utils);
|
rc = dsi_panel_parse_partial_update_caps(mode, utils);
|
||||||
if (rc)
|
if (rc)
|
||||||
DSI_ERR("failed to partial update caps, rc=%d\n", rc);
|
DSI_ERR("failed to partial update caps, rc=%d\n", rc);
|
||||||
|
|
||||||
if (panel->panel_mode_switch_enabled) {
|
|
||||||
rc = dsi_panel_parse_panel_mode_caps(mode, utils);
|
|
||||||
if (rc) {
|
|
||||||
rc = 0;
|
|
||||||
mode->panel_mode = panel->panel_mode;
|
|
||||||
DSI_INFO(
|
|
||||||
"POMS: panel mode isn't specified in timing[%d]\n",
|
|
||||||
child_idx);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mode->panel_mode = panel->panel_mode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@@ -180,7 +180,7 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
|||||||
old_conn_state->crtc);
|
old_conn_state->crtc);
|
||||||
|
|
||||||
if (!old_crtc_state->active ||
|
if (!old_crtc_state->active ||
|
||||||
!drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
|
!msm_atomic_needs_modeset(old_conn_state->crtc->state))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
encoder = old_conn_state->best_encoder;
|
encoder = old_conn_state->best_encoder;
|
||||||
@@ -221,7 +221,7 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
|||||||
const struct drm_crtc_helper_funcs *funcs;
|
const struct drm_crtc_helper_funcs *funcs;
|
||||||
|
|
||||||
/* Shut down everything that needs a full modeset. */
|
/* Shut down everything that needs a full modeset. */
|
||||||
if (!drm_atomic_crtc_needs_modeset(crtc->state))
|
if (!msm_atomic_needs_modeset(crtc->state))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!old_crtc_state->active)
|
if (!old_crtc_state->active)
|
||||||
@@ -294,7 +294,8 @@ msm_crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
|
|||||||
old_conn_state, false))
|
old_conn_state, false))
|
||||||
continue;
|
continue;
|
||||||
} else if (!new_crtc_state->mode_changed) {
|
} else if (!new_crtc_state->mode_changed) {
|
||||||
continue;
|
if (!msm_is_private_mode_changed(old_conn_state->crtc->state))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
|
DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
|
||||||
@@ -372,7 +373,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
|||||||
struct msm_display_mode *msm_mode;
|
struct msm_display_mode *msm_mode;
|
||||||
|
|
||||||
/* Need to filter out CRTCs where only planes change. */
|
/* Need to filter out CRTCs where only planes change. */
|
||||||
if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
|
if (!msm_atomic_needs_modeset(new_crtc_state))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!new_crtc_state->active)
|
if (!new_crtc_state->active)
|
||||||
@@ -416,8 +417,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!new_conn_state->crtc->state->active ||
|
if (!new_conn_state->crtc->state->active ||
|
||||||
!drm_atomic_crtc_needs_modeset(
|
!msm_atomic_needs_modeset(new_conn_state->crtc->state))
|
||||||
new_conn_state->crtc->state))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
old_conn_state = drm_atomic_get_old_connector_state(
|
old_conn_state = drm_atomic_get_old_connector_state(
|
||||||
@@ -466,8 +466,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!new_conn_state->crtc->state->active ||
|
if (!new_conn_state->crtc->state->active ||
|
||||||
!drm_atomic_crtc_needs_modeset(
|
!msm_atomic_needs_modeset(new_conn_state->crtc->state))
|
||||||
new_conn_state->crtc->state))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
old_conn_state = drm_atomic_get_old_connector_state(
|
old_conn_state = drm_atomic_get_old_connector_state(
|
||||||
|
@@ -214,6 +214,7 @@ enum msm_mdp_conn_property {
|
|||||||
CONNECTOR_PROP_FB_TRANSLATION_MODE,
|
CONNECTOR_PROP_FB_TRANSLATION_MODE,
|
||||||
CONNECTOR_PROP_QSYNC_MODE,
|
CONNECTOR_PROP_QSYNC_MODE,
|
||||||
CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
|
CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
|
||||||
|
CONNECTOR_PROP_SET_PANEL_MODE,
|
||||||
|
|
||||||
/* total # of properties */
|
/* total # of properties */
|
||||||
CONNECTOR_PROP_COUNT
|
CONNECTOR_PROP_COUNT
|
||||||
@@ -290,9 +291,9 @@ enum msm_display_caps {
|
|||||||
* @MODE_MAX:
|
* @MODE_MAX:
|
||||||
*/
|
*/
|
||||||
enum panel_op_mode {
|
enum panel_op_mode {
|
||||||
MSM_DISPLAY_VIDEO_MODE = 0,
|
MSM_DISPLAY_VIDEO_MODE = BIT(0),
|
||||||
MSM_DISPLAY_CMD_MODE,
|
MSM_DISPLAY_CMD_MODE = BIT(1),
|
||||||
MSM_DISPLAY_MODE_MAX,
|
MSM_DISPLAY_MODE_MAX = BIT(2)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -429,7 +430,6 @@ struct msm_display_dsc_info {
|
|||||||
* @flatqp_sw_nbls: flatness qp somewhat flat NBLs
|
* @flatqp_sw_nbls: flatness qp somewhat flat NBLs
|
||||||
* @chroma_samples: number of chroma samples
|
* @chroma_samples: number of chroma samples
|
||||||
* @split_panel_enable: indicates whether split panel is enabled
|
* @split_panel_enable: indicates whether split panel is enabled
|
||||||
* @panel_mode: indicates panel is in video or cmd mode
|
|
||||||
* @traffic_mode: indicates burst/non-burst mode
|
* @traffic_mode: indicates burst/non-burst mode
|
||||||
* @flatness_qp_lut: LUT used to determine flatness QP
|
* @flatness_qp_lut: LUT used to determine flatness QP
|
||||||
* @max_qp_lut: LUT used to determine maximum QP
|
* @max_qp_lut: LUT used to determine maximum QP
|
||||||
@@ -539,7 +539,6 @@ struct msm_display_vdc_info {
|
|||||||
u8 flatqp_sw_nbls;
|
u8 flatqp_sw_nbls;
|
||||||
u8 chroma_samples;
|
u8 chroma_samples;
|
||||||
u8 split_panel_enable;
|
u8 split_panel_enable;
|
||||||
u8 panel_mode;
|
|
||||||
u8 traffic_mode;
|
u8 traffic_mode;
|
||||||
|
|
||||||
u16 flatness_qp_lut[8];
|
u16 flatness_qp_lut[8];
|
||||||
@@ -693,6 +692,7 @@ struct msm_display_topology {
|
|||||||
* @comp_info: compression info supported
|
* @comp_info: compression info supported
|
||||||
* @roi_caps: panel roi capabilities
|
* @roi_caps: panel roi capabilities
|
||||||
* @wide_bus_en: wide-bus mode cfg for interface module
|
* @wide_bus_en: wide-bus mode cfg for interface module
|
||||||
|
* @panel_mode_caps panel mode capabilities
|
||||||
* @mdp_transfer_time_us Specifies the mdp transfer time for command mode
|
* @mdp_transfer_time_us Specifies the mdp transfer time for command mode
|
||||||
* panels in microseconds.
|
* panels in microseconds.
|
||||||
* @allowed_mode_switches: bit mask to indicate supported mode switch.
|
* @allowed_mode_switches: bit mask to indicate supported mode switch.
|
||||||
@@ -709,6 +709,7 @@ struct msm_mode_info {
|
|||||||
struct msm_compression_info comp_info;
|
struct msm_compression_info comp_info;
|
||||||
struct msm_roi_caps roi_caps;
|
struct msm_roi_caps roi_caps;
|
||||||
bool wide_bus_en;
|
bool wide_bus_en;
|
||||||
|
u32 panel_mode_caps;
|
||||||
u32 mdp_transfer_time_us;
|
u32 mdp_transfer_time_us;
|
||||||
u32 allowed_mode_switches;
|
u32 allowed_mode_switches;
|
||||||
};
|
};
|
||||||
|
@@ -38,12 +38,14 @@
|
|||||||
#define MSM_MODE_FLAG_SEAMLESS_DMS (1<<2)
|
#define MSM_MODE_FLAG_SEAMLESS_DMS (1<<2)
|
||||||
/* Request to switch the fps */
|
/* Request to switch the fps */
|
||||||
#define MSM_MODE_FLAG_SEAMLESS_VRR (1<<3)
|
#define MSM_MODE_FLAG_SEAMLESS_VRR (1<<3)
|
||||||
/* Request to switch the panel mode */
|
|
||||||
#define MSM_MODE_FLAG_SEAMLESS_POMS (1<<4)
|
|
||||||
/* Request to switch the bit clk */
|
/* Request to switch the bit clk */
|
||||||
#define MSM_MODE_FLAG_SEAMLESS_DYN_CLK (1<<5)
|
#define MSM_MODE_FLAG_SEAMLESS_DYN_CLK (1<<4)
|
||||||
/* Request to make the seamless switch */
|
/* Request to make the seamless switch */
|
||||||
#define DRM_MODE_FLAG_SEAMLESS (1<<6)
|
#define DRM_MODE_FLAG_SEAMLESS (1<<5)
|
||||||
|
/* Request to switch the panel mode to video */
|
||||||
|
#define MSM_MODE_FLAG_SEAMLESS_POMS_VID (1<<6)
|
||||||
|
/* Request to switch the panel mode to command */
|
||||||
|
#define MSM_MODE_FLAG_SEAMLESS_POMS_CMD (1<<7)
|
||||||
|
|
||||||
/* As there are different display controller blocks depending on the
|
/* As there are different display controller blocks depending on the
|
||||||
* snapdragon version, the kms support is split out and the appropriate
|
* snapdragon version, the kms support is split out and the appropriate
|
||||||
@@ -231,13 +233,27 @@ static inline bool msm_is_mode_seamless_vrr(const struct msm_display_mode *mode)
|
|||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool msm_is_mode_seamless_poms(
|
static inline bool msm_is_mode_seamless_poms_to_vid(
|
||||||
const struct msm_display_mode *mode)
|
const struct msm_display_mode *mode)
|
||||||
{
|
{
|
||||||
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_POMS)
|
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_POMS_VID)
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool msm_is_mode_seamless_poms_to_cmd(
|
||||||
|
const struct msm_display_mode *mode)
|
||||||
|
{
|
||||||
|
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_POMS_CMD)
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool msm_is_mode_seamless_poms(
|
||||||
|
const struct msm_display_mode *mode)
|
||||||
|
{
|
||||||
|
return (msm_is_mode_seamless_poms_to_vid(mode) ||
|
||||||
|
msm_is_mode_seamless_poms_to_cmd(mode));
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool msm_is_mode_seamless_dyn_clk(
|
static inline bool msm_is_mode_seamless_dyn_clk(
|
||||||
const struct msm_display_mode *mode)
|
const struct msm_display_mode *mode)
|
||||||
{
|
{
|
||||||
@@ -250,4 +266,42 @@ static inline bool msm_needs_vblank_pre_modeset(
|
|||||||
{
|
{
|
||||||
return (mode->private_flags & MSM_MODE_FLAG_VBLANK_PRE_MODESET);
|
return (mode->private_flags & MSM_MODE_FLAG_VBLANK_PRE_MODESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool msm_is_private_mode_changed(
|
||||||
|
struct drm_crtc_state *state)
|
||||||
|
{
|
||||||
|
struct msm_display_mode *msm_mode = NULL;
|
||||||
|
struct msm_drm_private *priv = NULL;
|
||||||
|
struct msm_kms *kms;
|
||||||
|
|
||||||
|
if (!state || !state->crtc)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
priv = state->crtc->dev->dev_private;
|
||||||
|
if (!priv)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
kms = priv->kms;
|
||||||
|
if (!kms || !kms->funcs->get_msm_mode)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
msm_mode = kms->funcs->get_msm_mode(state);
|
||||||
|
if (!msm_mode)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (msm_is_mode_seamless_poms(msm_mode))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool msm_atomic_needs_modeset(struct drm_crtc_state *state)
|
||||||
|
{
|
||||||
|
if (drm_atomic_crtc_needs_modeset(state))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (msm_is_private_mode_changed(state))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif /* __MSM_KMS_H__ */
|
#endif /* __MSM_KMS_H__ */
|
||||||
|
@@ -71,6 +71,11 @@ static const struct drm_prop_enum_list e_frame_trigger_mode[] = {
|
|||||||
{FRAME_DONE_WAIT_SERIALIZE, "serialize_frame_trigger"},
|
{FRAME_DONE_WAIT_SERIALIZE, "serialize_frame_trigger"},
|
||||||
{FRAME_DONE_WAIT_POSTED_START, "posted_start"},
|
{FRAME_DONE_WAIT_POSTED_START, "posted_start"},
|
||||||
};
|
};
|
||||||
|
static const struct drm_prop_enum_list e_panel_mode[] = {
|
||||||
|
{MSM_DISPLAY_VIDEO_MODE, "video_mode"},
|
||||||
|
{MSM_DISPLAY_CMD_MODE, "command_mode"},
|
||||||
|
{MSM_DISPLAY_MODE_MAX, "none"},
|
||||||
|
};
|
||||||
|
|
||||||
static inline struct sde_kms *_sde_connector_get_kms(struct drm_connector *conn)
|
static inline struct sde_kms *_sde_connector_get_kms(struct drm_connector *conn)
|
||||||
{
|
{
|
||||||
@@ -1553,6 +1558,14 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
|
|||||||
msm_property_set_dirty(&c_conn->property_info,
|
msm_property_set_dirty(&c_conn->property_info,
|
||||||
&c_state->property_state, idx);
|
&c_state->property_state, idx);
|
||||||
break;
|
break;
|
||||||
|
case CONNECTOR_PROP_SET_PANEL_MODE:
|
||||||
|
if (val == DRM_MODE_FLAG_VID_MODE_PANEL)
|
||||||
|
c_conn->expected_panel_mode =
|
||||||
|
MSM_DISPLAY_VIDEO_MODE;
|
||||||
|
else if (val == DRM_MODE_FLAG_CMD_MODE_PANEL)
|
||||||
|
c_conn->expected_panel_mode =
|
||||||
|
MSM_DISPLAY_CMD_MODE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2554,6 +2567,7 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn,
|
|||||||
|
|
||||||
list_for_each_entry(mode, &conn->modes, head) {
|
list_for_each_entry(mode, &conn->modes, head) {
|
||||||
int topology_idx = 0;
|
int topology_idx = 0;
|
||||||
|
u32 panel_mode_caps = 0;
|
||||||
|
|
||||||
memset(&mode_info, 0, sizeof(mode_info));
|
memset(&mode_info, 0, sizeof(mode_info));
|
||||||
|
|
||||||
@@ -2587,6 +2601,14 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn,
|
|||||||
sde_kms_info_add_keyint(info, "allowed_mode_switch",
|
sde_kms_info_add_keyint(info, "allowed_mode_switch",
|
||||||
mode_info.allowed_mode_switches);
|
mode_info.allowed_mode_switches);
|
||||||
|
|
||||||
|
if (mode_info.panel_mode_caps & DSI_OP_CMD_MODE)
|
||||||
|
panel_mode_caps |= DRM_MODE_FLAG_CMD_MODE_PANEL;
|
||||||
|
if (mode_info.panel_mode_caps & DSI_OP_VIDEO_MODE)
|
||||||
|
panel_mode_caps |= DRM_MODE_FLAG_VID_MODE_PANEL;
|
||||||
|
|
||||||
|
sde_kms_info_add_keyint(info, "panel_mode_capabilities",
|
||||||
|
panel_mode_caps);
|
||||||
|
|
||||||
if (!mode_info.roi_caps.num_roi)
|
if (!mode_info.roi_caps.num_roi)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -2792,6 +2814,14 @@ static int _sde_connector_install_properties(struct drm_device *dev,
|
|||||||
ARRAY_SIZE(e_frame_trigger_mode), 0,
|
ARRAY_SIZE(e_frame_trigger_mode), 0,
|
||||||
CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE);
|
CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE);
|
||||||
|
|
||||||
|
if (display_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE &&
|
||||||
|
display_info->capabilities & MSM_DISPLAY_CAP_VID_MODE)
|
||||||
|
msm_property_install_enum(&c_conn->property_info,
|
||||||
|
"panel_mode", 0, 0,
|
||||||
|
e_panel_mode,
|
||||||
|
ARRAY_SIZE(e_panel_mode), 0,
|
||||||
|
CONNECTOR_PROP_SET_PANEL_MODE);
|
||||||
|
|
||||||
if (sde_kms->catalog->has_demura) {
|
if (sde_kms->catalog->has_demura) {
|
||||||
msm_property_install_blob(&c_conn->property_info,
|
msm_property_install_blob(&c_conn->property_info,
|
||||||
"DEMURA_PANEL_ID", DRM_MODE_PROP_IMMUTABLE,
|
"DEMURA_PANEL_ID", DRM_MODE_PROP_IMMUTABLE,
|
||||||
|
@@ -459,6 +459,7 @@ struct sde_connector_dyn_hdr_metadata {
|
|||||||
* @thermal_max_brightness: thermal max brightness cap
|
* @thermal_max_brightness: thermal max brightness cap
|
||||||
* @status_work: work object to perform status checks
|
* @status_work: work object to perform status checks
|
||||||
* @esd_status_interval: variable to change ESD check interval in millisec
|
* @esd_status_interval: variable to change ESD check interval in millisec
|
||||||
|
* @expected_panel_mode: expected panel mode by usespace
|
||||||
* @panel_dead: Flag to indicate if panel has gone bad
|
* @panel_dead: Flag to indicate if panel has gone bad
|
||||||
* @esd_status_check: Flag to indicate if ESD thread is scheduled or not
|
* @esd_status_check: Flag to indicate if ESD thread is scheduled or not
|
||||||
* @bl_scale_dirty: Flag to indicate PP BL scale value(s) is changed
|
* @bl_scale_dirty: Flag to indicate PP BL scale value(s) is changed
|
||||||
@@ -523,6 +524,7 @@ struct sde_connector {
|
|||||||
u32 esd_status_interval;
|
u32 esd_status_interval;
|
||||||
bool panel_dead;
|
bool panel_dead;
|
||||||
bool esd_status_check;
|
bool esd_status_check;
|
||||||
|
enum panel_op_mode expected_panel_mode;
|
||||||
|
|
||||||
bool bl_scale_dirty;
|
bool bl_scale_dirty;
|
||||||
u32 bl_scale;
|
u32 bl_scale;
|
||||||
|
@@ -867,7 +867,7 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct drm_display_mode *adj_mode = &crtc_state->adjusted_mode;
|
struct drm_display_mode *adj_mode = &crtc_state->adjusted_mode;
|
||||||
|
|
||||||
if (sde_conn && drm_atomic_crtc_needs_modeset(crtc_state)) {
|
if (sde_conn && msm_atomic_needs_modeset(crtc_state)) {
|
||||||
struct msm_display_topology *topology = NULL;
|
struct msm_display_topology *topology = NULL;
|
||||||
|
|
||||||
ret = sde_connector_get_mode_info(&sde_conn->base,
|
ret = sde_connector_get_mode_info(&sde_conn->base,
|
||||||
@@ -2102,30 +2102,30 @@ static void sde_encoder_virt_mode_switch(struct drm_encoder *drm_enc,
|
|||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
|
struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
|
||||||
|
bool poms_to_vid = msm_is_mode_seamless_poms_to_vid(adj_mode);
|
||||||
|
bool poms_to_cmd = msm_is_mode_seamless_poms_to_cmd(adj_mode);
|
||||||
|
|
||||||
if (intf_mode == INTF_MODE_CMD)
|
if (poms_to_vid)
|
||||||
sde_enc->disp_info.curr_panel_mode = MSM_DISPLAY_VIDEO_MODE;
|
sde_enc->disp_info.curr_panel_mode = MSM_DISPLAY_VIDEO_MODE;
|
||||||
else if (intf_mode == INTF_MODE_VIDEO)
|
else if (poms_to_cmd)
|
||||||
sde_enc->disp_info.curr_panel_mode = MSM_DISPLAY_CMD_MODE;
|
sde_enc->disp_info.curr_panel_mode = MSM_DISPLAY_CMD_MODE;
|
||||||
|
|
||||||
_sde_encoder_update_rsc_client(drm_enc, true);
|
_sde_encoder_update_rsc_client(drm_enc, true);
|
||||||
|
|
||||||
if (intf_mode == INTF_MODE_CMD) {
|
if (intf_mode == INTF_MODE_CMD && poms_to_vid) {
|
||||||
for (i = 0; i < sde_enc->num_phys_encs; i++)
|
for (i = 0; i < sde_enc->num_phys_encs; i++)
|
||||||
sde_enc->phys_encs[i] = sde_enc->phys_vid_encs[i];
|
sde_enc->phys_encs[i] = sde_enc->phys_vid_encs[i];
|
||||||
|
|
||||||
SDE_DEBUG_ENC(sde_enc, "switch to video physical encoder\n");
|
SDE_DEBUG_ENC(sde_enc, "switch to video physical encoder\n");
|
||||||
SDE_EVT32(DRMID(&sde_enc->base), intf_mode,
|
SDE_EVT32(DRMID(&sde_enc->base), intf_mode, poms_to_cmd, poms_to_vid,
|
||||||
adj_mode->base->flags, adj_mode->private_flags,
|
SDE_EVTLOG_FUNC_CASE1);
|
||||||
SDE_EVTLOG_FUNC_CASE1);
|
} else if (intf_mode == INTF_MODE_VIDEO && poms_to_cmd) {
|
||||||
} else if (intf_mode == INTF_MODE_VIDEO) {
|
|
||||||
for (i = 0; i < sde_enc->num_phys_encs; i++)
|
for (i = 0; i < sde_enc->num_phys_encs; i++)
|
||||||
sde_enc->phys_encs[i] = sde_enc->phys_cmd_encs[i];
|
sde_enc->phys_encs[i] = sde_enc->phys_cmd_encs[i];
|
||||||
|
|
||||||
SDE_DEBUG_ENC(sde_enc, "switch to command physical encoder\n");
|
SDE_DEBUG_ENC(sde_enc, "switch to command physical encoder\n");
|
||||||
SDE_EVT32(DRMID(&sde_enc->base), intf_mode,
|
SDE_EVT32(DRMID(&sde_enc->base), intf_mode, poms_to_cmd, poms_to_vid,
|
||||||
adj_mode->base->flags, adj_mode->private_flags,
|
SDE_EVTLOG_FUNC_CASE2);
|
||||||
SDE_EVTLOG_FUNC_CASE2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2218,19 +2218,6 @@ static void _sde_encoder_virt_populate_hw_res(struct drm_encoder *drm_enc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sde_encoder_detect_panel_mode_switch(
|
|
||||||
struct drm_display_mode *adj_mode, enum sde_intf_mode intf_mode)
|
|
||||||
{
|
|
||||||
/* don't rely on POMS flag as it may not be set for power-on modeset */
|
|
||||||
if ((intf_mode == INTF_MODE_CMD &&
|
|
||||||
adj_mode->flags & DRM_MODE_FLAG_VID_MODE_PANEL) ||
|
|
||||||
(intf_mode == INTF_MODE_VIDEO &&
|
|
||||||
adj_mode->flags & DRM_MODE_FLAG_CMD_MODE_PANEL))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sde_encoder_virt_modeset_rc(struct drm_encoder *drm_enc,
|
static int sde_encoder_virt_modeset_rc(struct drm_encoder *drm_enc,
|
||||||
struct msm_display_mode *msm_mode, bool pre_modeset)
|
struct msm_display_mode *msm_mode, bool pre_modeset)
|
||||||
{
|
{
|
||||||
@@ -2262,8 +2249,7 @@ static int sde_encoder_virt_modeset_rc(struct drm_encoder *drm_enc,
|
|||||||
* modeset to guarantee previous kickoff has finished.
|
* modeset to guarantee previous kickoff has finished.
|
||||||
*/
|
*/
|
||||||
sde_encoder_dce_disable(sde_enc);
|
sde_encoder_dce_disable(sde_enc);
|
||||||
} else if (sde_encoder_detect_panel_mode_switch(msm_mode->base,
|
} else if (msm_is_mode_seamless_poms(msm_mode)) {
|
||||||
intf_mode)) {
|
|
||||||
_sde_encoder_modeset_helper_locked(drm_enc,
|
_sde_encoder_modeset_helper_locked(drm_enc,
|
||||||
SDE_ENC_RC_EVENT_PRE_MODESET);
|
SDE_ENC_RC_EVENT_PRE_MODESET);
|
||||||
sde_encoder_virt_mode_switch(drm_enc, intf_mode,
|
sde_encoder_virt_mode_switch(drm_enc, intf_mode,
|
||||||
|
@@ -259,7 +259,8 @@ static void _dce_vdc_pipe_cfg(struct sde_hw_vdc *hw_vdc,
|
|||||||
struct sde_hw_pingpong *hw_pp,
|
struct sde_hw_pingpong *hw_pp,
|
||||||
struct msm_display_vdc_info *vdc,
|
struct msm_display_vdc_info *vdc,
|
||||||
enum sde_3d_blend_mode mode_3d,
|
enum sde_3d_blend_mode mode_3d,
|
||||||
bool disable_merge_3d, bool enable)
|
bool disable_merge_3d, bool enable,
|
||||||
|
bool is_video_mode)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!vdc || !hw_vdc || !hw_pp) {
|
if (!vdc || !hw_vdc || !hw_pp) {
|
||||||
@@ -282,7 +283,7 @@ static void _dce_vdc_pipe_cfg(struct sde_hw_vdc *hw_vdc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hw_vdc->ops.vdc_config)
|
if (hw_vdc->ops.vdc_config)
|
||||||
hw_vdc->ops.vdc_config(hw_vdc, vdc);
|
hw_vdc->ops.vdc_config(hw_vdc, vdc, is_video_mode);
|
||||||
|
|
||||||
if (mode_3d && disable_merge_3d && hw_pp->ops.reset_3d_mode) {
|
if (mode_3d && disable_merge_3d && hw_pp->ops.reset_3d_mode) {
|
||||||
SDE_DEBUG("disabling 3d mux\n");
|
SDE_DEBUG("disabling 3d mux\n");
|
||||||
@@ -553,6 +554,7 @@ static int _dce_vdc_setup(struct sde_encoder_virt *sde_enc,
|
|||||||
int intf_ip_w, enc_ip_w;
|
int intf_ip_w, enc_ip_w;
|
||||||
const struct sde_rm_topology_def *def;
|
const struct sde_rm_topology_def *def;
|
||||||
int num_intf, num_vdc, num_lm;
|
int num_intf, num_vdc, num_lm;
|
||||||
|
bool is_video_mode = false;
|
||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -625,6 +627,8 @@ static int _dce_vdc_setup(struct sde_encoder_virt *sde_enc,
|
|||||||
SDE_DEBUG_DCE(sde_enc, "pic_w: %d pic_h: %d\n",
|
SDE_DEBUG_DCE(sde_enc, "pic_w: %d pic_h: %d\n",
|
||||||
roi->w, roi->h);
|
roi->w, roi->h);
|
||||||
|
|
||||||
|
is_video_mode = sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_VIDEO_MODE);
|
||||||
|
|
||||||
for (i = 0; i < num_vdc; i++) {
|
for (i = 0; i < num_vdc; i++) {
|
||||||
bool active = !!((1 << i) & params->affected_displays);
|
bool active = !!((1 << i) & params->affected_displays);
|
||||||
|
|
||||||
@@ -649,7 +653,8 @@ static int _dce_vdc_setup(struct sde_encoder_virt *sde_enc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_dce_vdc_pipe_cfg(hw_vdc[i], hw_pp[i],
|
_dce_vdc_pipe_cfg(hw_vdc[i], hw_pp[i],
|
||||||
vdc, mode_3d, disable_merge_3d, active);
|
vdc, mode_3d, disable_merge_3d,
|
||||||
|
active, is_video_mode);
|
||||||
|
|
||||||
memset(&cfg, 0, sizeof(cfg));
|
memset(&cfg, 0, sizeof(cfg));
|
||||||
cfg.vdc[cfg.vdc_count++] = hw_vdc[i]->idx;
|
cfg.vdc[cfg.vdc_count++] = hw_vdc[i]->idx;
|
||||||
@@ -763,6 +768,7 @@ static void _dce_vdc_disable(struct sde_encoder_virt *sde_enc)
|
|||||||
struct sde_hw_vdc *hw_vdc = NULL;
|
struct sde_hw_vdc *hw_vdc = NULL;
|
||||||
struct sde_hw_ctl *hw_ctl = NULL;
|
struct sde_hw_ctl *hw_ctl = NULL;
|
||||||
struct sde_hw_intf_cfg_v1 cfg;
|
struct sde_hw_intf_cfg_v1 cfg;
|
||||||
|
bool is_video_mode = false;
|
||||||
|
|
||||||
if (!sde_enc || !sde_enc->phys_encs[0] ||
|
if (!sde_enc || !sde_enc->phys_encs[0] ||
|
||||||
!sde_enc->phys_encs[0]->connector) {
|
!sde_enc->phys_encs[0]->connector) {
|
||||||
@@ -776,6 +782,7 @@ static void _dce_vdc_disable(struct sde_encoder_virt *sde_enc)
|
|||||||
|
|
||||||
memset(&cfg, 0, sizeof(cfg));
|
memset(&cfg, 0, sizeof(cfg));
|
||||||
|
|
||||||
|
is_video_mode = sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_VIDEO_MODE);
|
||||||
/* Disable VDC for all the pp's present in this topology */
|
/* Disable VDC for all the pp's present in this topology */
|
||||||
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
|
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
|
||||||
hw_pp = sde_enc->hw_pp[i];
|
hw_pp = sde_enc->hw_pp[i];
|
||||||
@@ -783,7 +790,7 @@ static void _dce_vdc_disable(struct sde_encoder_virt *sde_enc)
|
|||||||
|
|
||||||
_dce_vdc_pipe_cfg(hw_vdc, hw_pp, NULL,
|
_dce_vdc_pipe_cfg(hw_vdc, hw_pp, NULL,
|
||||||
BLEND_3D_NONE, false,
|
BLEND_3D_NONE, false,
|
||||||
false);
|
false, is_video_mode);
|
||||||
|
|
||||||
if (hw_vdc) {
|
if (hw_vdc) {
|
||||||
sde_enc->dirty_vdc_ids[i] = hw_vdc->idx;
|
sde_enc->dirty_vdc_ids[i] = hw_vdc->idx;
|
||||||
|
@@ -108,7 +108,7 @@ static void sde_hw_vdc_disable(struct sde_hw_vdc *hw_vdc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sde_hw_vdc_config(struct sde_hw_vdc *hw_vdc,
|
static void sde_hw_vdc_config(struct sde_hw_vdc *hw_vdc,
|
||||||
struct msm_display_vdc_info *vdc)
|
struct msm_display_vdc_info *vdc, bool is_video_mode)
|
||||||
{
|
{
|
||||||
struct sde_hw_blk_reg_map *vdc_reg = &hw_vdc->hw;
|
struct sde_hw_blk_reg_map *vdc_reg = &hw_vdc->hw;
|
||||||
u32 idx;
|
u32 idx;
|
||||||
@@ -136,7 +136,7 @@ static void sde_hw_vdc_config(struct sde_hw_vdc *hw_vdc,
|
|||||||
SDE_REG_WRITE(vdc_reg, ENC_ORIG_SLICE + idx, data);
|
SDE_REG_WRITE(vdc_reg, ENC_ORIG_SLICE + idx, data);
|
||||||
|
|
||||||
data = 0;
|
data = 0;
|
||||||
if (vdc->panel_mode == VDC_VIDEO_MODE)
|
if (is_video_mode)
|
||||||
data |= BIT(9);
|
data |= BIT(9);
|
||||||
data |= ((vdc->num_of_active_ss - 1) << 12);
|
data |= ((vdc->num_of_active_ss - 1) << 12);
|
||||||
data |= vdc->initial_lines;
|
data |= vdc->initial_lines;
|
||||||
|
@@ -29,9 +29,10 @@ struct sde_hw_vdc_ops {
|
|||||||
* vdc_config - configures vdc encoder
|
* vdc_config - configures vdc encoder
|
||||||
* @hw_vdc: Pointer to vdc context
|
* @hw_vdc: Pointer to vdc context
|
||||||
* @vdc: panel vdc parameters
|
* @vdc: panel vdc parameters
|
||||||
|
* @is_video_mode: current panel mode is video
|
||||||
*/
|
*/
|
||||||
void (*vdc_config)(struct sde_hw_vdc *hw_vdc,
|
void (*vdc_config)(struct sde_hw_vdc *hw_vdc,
|
||||||
struct msm_display_vdc_info *vdc);
|
struct msm_display_vdc_info *vdc, bool is_video_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bind_pingpong_blk - enable/disable the connection with pp
|
* bind_pingpong_blk - enable/disable the connection with pp
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define pr_fmt(fmt) "[drm:%s] " fmt, __func__
|
#define pr_fmt(fmt) "[drm:%s] " fmt, __func__
|
||||||
@@ -2434,7 +2434,7 @@ int sde_rm_reserve(
|
|||||||
|
|
||||||
/* Check if this is just a page-flip */
|
/* Check if this is just a page-flip */
|
||||||
if (!_sde_rm_is_display_in_cont_splash(sde_kms, enc) &&
|
if (!_sde_rm_is_display_in_cont_splash(sde_kms, enc) &&
|
||||||
!drm_atomic_crtc_needs_modeset(crtc_state))
|
!msm_atomic_needs_modeset(crtc_state))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
comp_info = kzalloc(sizeof(*comp_info), GFP_KERNEL);
|
comp_info = kzalloc(sizeof(*comp_info), GFP_KERNEL);
|
||||||
|
Reference in New Issue
Block a user