disp: msm: move from drm_mode to msm_mode
Move away from the private and private_flags fields from drm_mode, as it is being deprecated in latest kernel version. Instead, Add msm_display_mode as a wrapper to be used in downstream to store these parameters. Also, store msm_mode in connector_state to be accessed in commit path. Change-Id: Ia5bdebe75f00aa15fb7db4dc3a0d50c30894a95c Signed-off-by: Orion Brody <obrody@codeaurora.org>
This commit is contained in:
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
#include "dsi_drm.h"
|
#include "dsi_drm.h"
|
||||||
#include "sde_trace.h"
|
#include "sde_trace.h"
|
||||||
#include "sde_dbg.h"
|
#include "sde_dbg.h"
|
||||||
|
#include "msm_drv.h"
|
||||||
|
#include "sde_encoder.h"
|
||||||
|
|
||||||
#define to_dsi_bridge(x) container_of((x), struct dsi_bridge, base)
|
#define to_dsi_bridge(x) container_of((x), struct dsi_bridge, base)
|
||||||
#define to_dsi_state(x) container_of((x), struct dsi_connector_state, base)
|
#define to_dsi_state(x) container_of((x), struct dsi_connector_state, base)
|
||||||
@@ -53,32 +55,6 @@ static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode,
|
|||||||
|
|
||||||
dsi_mode->pixel_clk_khz = drm_mode->clock;
|
dsi_mode->pixel_clk_khz = drm_mode->clock;
|
||||||
|
|
||||||
dsi_mode->priv_info =
|
|
||||||
(struct dsi_display_mode_priv_info *)drm_mode->private;
|
|
||||||
|
|
||||||
if (dsi_mode->priv_info) {
|
|
||||||
dsi_mode->timing.dsc_enabled = dsi_mode->priv_info->dsc_enabled;
|
|
||||||
dsi_mode->timing.dsc = &dsi_mode->priv_info->dsc;
|
|
||||||
dsi_mode->timing.vdc_enabled = dsi_mode->priv_info->vdc_enabled;
|
|
||||||
dsi_mode->timing.vdc = &dsi_mode->priv_info->vdc;
|
|
||||||
dsi_mode->timing.pclk_scale = dsi_mode->priv_info->pclk_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msm_is_mode_seamless(drm_mode))
|
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_SEAMLESS;
|
|
||||||
if (msm_is_mode_dynamic_fps(drm_mode))
|
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DFPS;
|
|
||||||
if (msm_needs_vblank_pre_modeset(drm_mode))
|
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VBLANK_PRE_MODESET;
|
|
||||||
if (msm_is_mode_seamless_dms(drm_mode))
|
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
|
|
||||||
if (msm_is_mode_seamless_vrr(drm_mode))
|
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
|
|
||||||
if (msm_is_mode_seamless_poms(drm_mode))
|
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS;
|
|
||||||
if (msm_is_mode_seamless_dyn_clk(drm_mode))
|
|
||||||
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DYN_CLK;
|
|
||||||
|
|
||||||
dsi_mode->timing.h_sync_polarity =
|
dsi_mode->timing.h_sync_polarity =
|
||||||
!!(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 =
|
||||||
@@ -90,6 +66,36 @@ static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode,
|
|||||||
dsi_mode->panel_mode = DSI_OP_CMD_MODE;
|
dsi_mode->panel_mode = DSI_OP_CMD_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msm_parse_mode_priv_info(const struct msm_display_mode *msm_mode,
|
||||||
|
struct dsi_display_mode *dsi_mode)
|
||||||
|
{
|
||||||
|
dsi_mode->priv_info =
|
||||||
|
(struct dsi_display_mode_priv_info *)msm_mode->private;
|
||||||
|
|
||||||
|
if (dsi_mode->priv_info) {
|
||||||
|
dsi_mode->timing.dsc_enabled = dsi_mode->priv_info->dsc_enabled;
|
||||||
|
dsi_mode->timing.dsc = &dsi_mode->priv_info->dsc;
|
||||||
|
dsi_mode->timing.vdc_enabled = dsi_mode->priv_info->vdc_enabled;
|
||||||
|
dsi_mode->timing.vdc = &dsi_mode->priv_info->vdc;
|
||||||
|
dsi_mode->timing.pclk_scale = dsi_mode->priv_info->pclk_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msm_is_mode_seamless(msm_mode))
|
||||||
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_SEAMLESS;
|
||||||
|
if (msm_is_mode_dynamic_fps(msm_mode))
|
||||||
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DFPS;
|
||||||
|
if (msm_needs_vblank_pre_modeset(msm_mode))
|
||||||
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VBLANK_PRE_MODESET;
|
||||||
|
if (msm_is_mode_seamless_dms(msm_mode))
|
||||||
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
|
||||||
|
if (msm_is_mode_seamless_vrr(msm_mode))
|
||||||
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
|
||||||
|
if (msm_is_mode_seamless_poms(msm_mode))
|
||||||
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS;
|
||||||
|
if (msm_is_mode_seamless_dyn_clk(msm_mode))
|
||||||
|
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DYN_CLK;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -115,23 +121,6 @@ void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
|
|||||||
drm_mode->vrefresh = dsi_mode->timing.refresh_rate;
|
drm_mode->vrefresh = dsi_mode->timing.refresh_rate;
|
||||||
drm_mode->clock = dsi_mode->pixel_clk_khz;
|
drm_mode->clock = dsi_mode->pixel_clk_khz;
|
||||||
|
|
||||||
drm_mode->private = (int *)dsi_mode->priv_info;
|
|
||||||
|
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS)
|
|
||||||
drm_mode->private_flags |= DRM_MODE_FLAG_SEAMLESS;
|
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DFPS)
|
|
||||||
drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS;
|
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VBLANK_PRE_MODESET)
|
|
||||||
drm_mode->private_flags |= MSM_MODE_FLAG_VBLANK_PRE_MODESET;
|
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DMS)
|
|
||||||
drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS;
|
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR)
|
|
||||||
drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR;
|
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS)
|
|
||||||
drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_POMS;
|
|
||||||
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK)
|
|
||||||
drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYN_CLK;
|
|
||||||
|
|
||||||
if (dsi_mode->timing.h_sync_polarity)
|
if (dsi_mode->timing.h_sync_polarity)
|
||||||
drm_mode->flags |= DRM_MODE_FLAG_PHSYNC;
|
drm_mode->flags |= DRM_MODE_FLAG_PHSYNC;
|
||||||
if (dsi_mode->timing.v_sync_polarity)
|
if (dsi_mode->timing.v_sync_polarity)
|
||||||
@@ -149,6 +138,28 @@ void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
|
|||||||
video_mode ? "vid" : "cmd");
|
video_mode ? "vid" : "cmd");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dsi_convert_to_msm_mode(const struct dsi_display_mode *dsi_mode,
|
||||||
|
struct msm_display_mode *msm_mode)
|
||||||
|
{
|
||||||
|
msm_mode->private_flags = 0;
|
||||||
|
msm_mode->private = (int *)dsi_mode->priv_info;
|
||||||
|
|
||||||
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS)
|
||||||
|
msm_mode->private_flags |= DRM_MODE_FLAG_SEAMLESS;
|
||||||
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DFPS)
|
||||||
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS;
|
||||||
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VBLANK_PRE_MODESET)
|
||||||
|
msm_mode->private_flags |= MSM_MODE_FLAG_VBLANK_PRE_MODESET;
|
||||||
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DMS)
|
||||||
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS;
|
||||||
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR)
|
||||||
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR;
|
||||||
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS)
|
||||||
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_POMS;
|
||||||
|
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK)
|
||||||
|
msm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYN_CLK;
|
||||||
|
}
|
||||||
|
|
||||||
static int dsi_bridge_attach(struct drm_bridge *bridge,
|
static int dsi_bridge_attach(struct drm_bridge *bridge,
|
||||||
enum drm_bridge_attach_flags flags)
|
enum drm_bridge_attach_flags flags)
|
||||||
{
|
{
|
||||||
@@ -261,8 +272,8 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
|
|||||||
static void dsi_bridge_disable(struct drm_bridge *bridge)
|
static void dsi_bridge_disable(struct drm_bridge *bridge)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int private_flags;
|
|
||||||
struct dsi_display *display;
|
struct dsi_display *display;
|
||||||
|
struct sde_connector_state *conn_state;
|
||||||
struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
|
struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
|
||||||
|
|
||||||
if (!bridge) {
|
if (!bridge) {
|
||||||
@@ -270,15 +281,19 @@ static void dsi_bridge_disable(struct drm_bridge *bridge)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
display = c_bridge->display;
|
display = c_bridge->display;
|
||||||
private_flags =
|
|
||||||
bridge->encoder->crtc->state->adjusted_mode.private_flags;
|
|
||||||
|
|
||||||
if (display)
|
if (display)
|
||||||
display->enabled = false;
|
display->enabled = false;
|
||||||
|
|
||||||
if (display && display->drm_conn) {
|
if (display && display->drm_conn) {
|
||||||
display->poms_pending =
|
conn_state = to_sde_connector_state(display->drm_conn->state);
|
||||||
private_flags & MSM_MODE_FLAG_SEAMLESS_POMS;
|
if (!conn_state) {
|
||||||
|
DSI_ERR("invalid params\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
display->poms_pending = msm_is_mode_seamless_poms(
|
||||||
|
&conn_state->msm_mode);
|
||||||
|
|
||||||
sde_connector_helper_bridge_disable(display->drm_conn);
|
sde_connector_helper_bridge_disable(display->drm_conn);
|
||||||
}
|
}
|
||||||
@@ -326,6 +341,8 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
|
|||||||
const struct drm_display_mode *adjusted_mode)
|
const struct drm_display_mode *adjusted_mode)
|
||||||
{
|
{
|
||||||
struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
|
struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
|
||||||
|
struct drm_connector *conn;
|
||||||
|
struct sde_connector_state *conn_state;
|
||||||
|
|
||||||
if (!bridge || !mode || !adjusted_mode) {
|
if (!bridge || !mode || !adjusted_mode) {
|
||||||
DSI_ERR("Invalid params\n");
|
DSI_ERR("Invalid params\n");
|
||||||
@@ -334,6 +351,18 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
|
|||||||
|
|
||||||
memset(&(c_bridge->dsi_mode), 0x0, sizeof(struct dsi_display_mode));
|
memset(&(c_bridge->dsi_mode), 0x0, sizeof(struct dsi_display_mode));
|
||||||
convert_to_dsi_mode(adjusted_mode, &(c_bridge->dsi_mode));
|
convert_to_dsi_mode(adjusted_mode, &(c_bridge->dsi_mode));
|
||||||
|
conn = sde_encoder_get_connector(bridge->dev, bridge->encoder);
|
||||||
|
if (!conn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
conn_state = to_sde_connector_state(conn->state);
|
||||||
|
if (!conn_state) {
|
||||||
|
DSI_ERR("invalid connector state\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
msm_parse_mode_priv_info(&conn_state->msm_mode,
|
||||||
|
&(c_bridge->dsi_mode));
|
||||||
|
|
||||||
/* restore bit_clk_rate also for dynamic clk use cases */
|
/* restore bit_clk_rate also for dynamic clk use cases */
|
||||||
c_bridge->dsi_mode.timing.clk_rate_hz =
|
c_bridge->dsi_mode.timing.clk_rate_hz =
|
||||||
@@ -351,17 +380,27 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
|||||||
struct dsi_display *display;
|
struct dsi_display *display;
|
||||||
struct dsi_display_mode dsi_mode, cur_dsi_mode, *panel_dsi_mode;
|
struct dsi_display_mode dsi_mode, cur_dsi_mode, *panel_dsi_mode;
|
||||||
struct drm_crtc_state *crtc_state;
|
struct drm_crtc_state *crtc_state;
|
||||||
|
struct drm_connector_state *drm_conn_state;
|
||||||
|
struct sde_connector_state *conn_state;
|
||||||
|
|
||||||
crtc_state = container_of(mode, struct drm_crtc_state, mode);
|
crtc_state = container_of(mode, struct drm_crtc_state, mode);
|
||||||
|
|
||||||
if (!bridge || !mode || !adjusted_mode) {
|
if (!bridge || !mode || !adjusted_mode) {
|
||||||
DSI_ERR("Invalid params\n");
|
DSI_ERR("invalid params\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
display = c_bridge->display;
|
display = c_bridge->display;
|
||||||
if (!display) {
|
if (!display || !display->drm_conn || !display->drm_conn->state) {
|
||||||
DSI_ERR("Invalid params\n");
|
DSI_ERR("invalid params\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_conn_state = drm_atomic_get_new_connector_state(crtc_state->state,
|
||||||
|
display->drm_conn);
|
||||||
|
conn_state = to_sde_connector_state(drm_conn_state);
|
||||||
|
if (!conn_state) {
|
||||||
|
DSI_ERR("invalid params\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,8 +410,9 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
|||||||
*/
|
*/
|
||||||
if (display->panel && !display->panel->num_timing_nodes) {
|
if (display->panel && !display->panel->num_timing_nodes) {
|
||||||
*adjusted_mode = *mode;
|
*adjusted_mode = *mode;
|
||||||
adjusted_mode->private = (int *)&default_priv_info;
|
conn_state->msm_mode.base = adjusted_mode;
|
||||||
adjusted_mode->private_flags = 0;
|
conn_state->msm_mode.private = (int *)&default_priv_info;
|
||||||
|
conn_state->msm_mode.private_flags = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,7 +499,7 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
|||||||
|
|
||||||
/* convert back to drm mode, propagating the private info & flags */
|
/* convert back to drm mode, propagating the private info & flags */
|
||||||
dsi_convert_to_drm_mode(&dsi_mode, adjusted_mode);
|
dsi_convert_to_drm_mode(&dsi_mode, adjusted_mode);
|
||||||
|
dsi_convert_to_msm_mode(&dsi_mode, &conn_state->msm_mode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,61 +557,61 @@ int dsi_conn_get_mode_info(struct drm_connector *connector,
|
|||||||
struct msm_mode_info *mode_info,
|
struct msm_mode_info *mode_info,
|
||||||
void *display, const struct msm_resource_caps_info *avail_res)
|
void *display, const struct msm_resource_caps_info *avail_res)
|
||||||
{
|
{
|
||||||
struct dsi_display_mode dsi_mode;
|
struct dsi_display_mode partial_dsi_mode, *dsi_mode = NULL;
|
||||||
struct dsi_mode_info *timing;
|
struct dsi_mode_info *timing;
|
||||||
int src_bpp, tar_bpp;
|
int src_bpp, tar_bpp, rc = 0;
|
||||||
|
|
||||||
if (!drm_mode || !mode_info)
|
if (!drm_mode || !mode_info)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
convert_to_dsi_mode(drm_mode, &dsi_mode);
|
convert_to_dsi_mode(drm_mode, &partial_dsi_mode);
|
||||||
|
rc = dsi_display_find_mode(display, &partial_dsi_mode, &dsi_mode);
|
||||||
if (!dsi_mode.priv_info)
|
if (rc || !dsi_mode->priv_info)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
memset(mode_info, 0, sizeof(*mode_info));
|
memset(mode_info, 0, sizeof(*mode_info));
|
||||||
|
|
||||||
timing = &dsi_mode.timing;
|
timing = &dsi_mode->timing;
|
||||||
mode_info->frame_rate = dsi_mode.timing.refresh_rate;
|
mode_info->frame_rate = dsi_mode->timing.refresh_rate;
|
||||||
mode_info->vtotal = DSI_V_TOTAL(timing);
|
mode_info->vtotal = DSI_V_TOTAL(timing);
|
||||||
mode_info->prefill_lines = dsi_mode.priv_info->panel_prefill_lines;
|
mode_info->prefill_lines = dsi_mode->priv_info->panel_prefill_lines;
|
||||||
mode_info->jitter_numer = dsi_mode.priv_info->panel_jitter_numer;
|
mode_info->jitter_numer = dsi_mode->priv_info->panel_jitter_numer;
|
||||||
mode_info->jitter_denom = dsi_mode.priv_info->panel_jitter_denom;
|
mode_info->jitter_denom = dsi_mode->priv_info->panel_jitter_denom;
|
||||||
mode_info->clk_rate = dsi_drm_find_bit_clk_rate(display, drm_mode);
|
|
||||||
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->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;
|
||||||
|
|
||||||
memcpy(&mode_info->topology, &dsi_mode.priv_info->topology,
|
memcpy(&mode_info->topology, &dsi_mode->priv_info->topology,
|
||||||
sizeof(struct msm_display_topology));
|
sizeof(struct msm_display_topology));
|
||||||
|
|
||||||
if (dsi_mode.priv_info->dsc_enabled) {
|
if (dsi_mode->priv_info->dsc_enabled) {
|
||||||
mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_DSC;
|
mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_DSC;
|
||||||
mode_info->topology.comp_type = MSM_DISPLAY_COMPRESSION_DSC;
|
mode_info->topology.comp_type = MSM_DISPLAY_COMPRESSION_DSC;
|
||||||
memcpy(&mode_info->comp_info.dsc_info, &dsi_mode.priv_info->dsc,
|
memcpy(&mode_info->comp_info.dsc_info, &dsi_mode->priv_info->dsc,
|
||||||
sizeof(dsi_mode.priv_info->dsc));
|
sizeof(dsi_mode->priv_info->dsc));
|
||||||
} else if (dsi_mode.priv_info->vdc_enabled) {
|
} else if (dsi_mode->priv_info->vdc_enabled) {
|
||||||
mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_VDC;
|
mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_VDC;
|
||||||
mode_info->topology.comp_type = MSM_DISPLAY_COMPRESSION_VDC;
|
mode_info->topology.comp_type = MSM_DISPLAY_COMPRESSION_VDC;
|
||||||
memcpy(&mode_info->comp_info.vdc_info, &dsi_mode.priv_info->vdc,
|
memcpy(&mode_info->comp_info.vdc_info, &dsi_mode->priv_info->vdc,
|
||||||
sizeof(dsi_mode.priv_info->vdc));
|
sizeof(dsi_mode->priv_info->vdc));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode_info->comp_info.comp_type) {
|
if (mode_info->comp_info.comp_type) {
|
||||||
tar_bpp = dsi_mode.priv_info->pclk_scale.numer;
|
tar_bpp = dsi_mode->priv_info->pclk_scale.numer;
|
||||||
src_bpp = dsi_mode.priv_info->pclk_scale.denom;
|
src_bpp = dsi_mode->priv_info->pclk_scale.denom;
|
||||||
mode_info->comp_info.comp_ratio = mult_frac(1, src_bpp,
|
mode_info->comp_info.comp_ratio = mult_frac(1, src_bpp,
|
||||||
tar_bpp);
|
tar_bpp);
|
||||||
mode_info->wide_bus_en = dsi_mode.priv_info->widebus_support;
|
mode_info->wide_bus_en = dsi_mode->priv_info->widebus_support;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dsi_mode.priv_info->roi_caps.enabled) {
|
if (dsi_mode->priv_info->roi_caps.enabled) {
|
||||||
memcpy(&mode_info->roi_caps, &dsi_mode.priv_info->roi_caps,
|
memcpy(&mode_info->roi_caps, &dsi_mode->priv_info->roi_caps,
|
||||||
sizeof(dsi_mode.priv_info->roi_caps));
|
sizeof(dsi_mode->priv_info->roi_caps));
|
||||||
}
|
}
|
||||||
|
|
||||||
mode_info->allowed_mode_switches =
|
mode_info->allowed_mode_switches =
|
||||||
dsi_mode.priv_info->allowed_mode_switch;
|
dsi_mode->priv_info->allowed_mode_switch;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -766,15 +806,20 @@ void dsi_connector_put_modes(struct drm_connector *connector,
|
|||||||
void *display)
|
void *display)
|
||||||
{
|
{
|
||||||
struct drm_display_mode *drm_mode;
|
struct drm_display_mode *drm_mode;
|
||||||
struct dsi_display_mode dsi_mode;
|
struct dsi_display_mode dsi_mode, *full_dsi_mode = NULL;
|
||||||
struct dsi_display *dsi_display;
|
struct dsi_display *dsi_display;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
if (!connector || !display)
|
if (!connector || !display)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list_for_each_entry(drm_mode, &connector->modes, head) {
|
list_for_each_entry(drm_mode, &connector->modes, head) {
|
||||||
convert_to_dsi_mode(drm_mode, &dsi_mode);
|
convert_to_dsi_mode(drm_mode, &dsi_mode);
|
||||||
dsi_display_put_mode(display, &dsi_mode);
|
rc = dsi_display_find_mode(display, &dsi_mode, &full_dsi_mode);
|
||||||
|
if (rc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dsi_display_put_mode(display, full_dsi_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free the display structure modes also */
|
/* free the display structure modes also */
|
||||||
@@ -964,6 +1009,7 @@ enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector,
|
|||||||
void *display, const struct msm_resource_caps_info *avail_res)
|
void *display, const struct msm_resource_caps_info *avail_res)
|
||||||
{
|
{
|
||||||
struct dsi_display_mode dsi_mode;
|
struct dsi_display_mode dsi_mode;
|
||||||
|
struct dsi_display_mode *full_dsi_mode = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!connector || !mode) {
|
if (!connector || !mode) {
|
||||||
@@ -972,8 +1018,13 @@ enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector,
|
|||||||
}
|
}
|
||||||
|
|
||||||
convert_to_dsi_mode(mode, &dsi_mode);
|
convert_to_dsi_mode(mode, &dsi_mode);
|
||||||
|
rc = dsi_display_find_mode(display, &dsi_mode, &full_dsi_mode);
|
||||||
|
if (rc) {
|
||||||
|
DSI_ERR("could not find mode %s\n", mode->name);
|
||||||
|
return MODE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
rc = dsi_display_validate_mode(display, &dsi_mode,
|
rc = dsi_display_validate_mode(display, full_dsi_mode,
|
||||||
DSI_VALIDATE_FLAG_ALLOW_ADJUST);
|
DSI_VALIDATE_FLAG_ALLOW_ADJUST);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DSI_ERR("mode not supported, rc=%d\n", rc);
|
DSI_ERR("mode not supported, rc=%d\n", rc);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2014 Red Hat
|
* Copyright (C) 2014 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -40,16 +40,25 @@ static inline bool _msm_seamless_for_crtc(struct drm_atomic_state *state,
|
|||||||
{
|
{
|
||||||
struct drm_connector *connector = NULL;
|
struct drm_connector *connector = NULL;
|
||||||
struct drm_connector_state *conn_state = NULL;
|
struct drm_connector_state *conn_state = NULL;
|
||||||
|
struct msm_display_mode *msm_mode;
|
||||||
|
struct msm_drm_private *priv = state->dev->dev_private;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int conn_cnt = 0;
|
int conn_cnt = 0;
|
||||||
|
|
||||||
if (msm_is_mode_seamless(&crtc_state->mode) ||
|
if (!priv || !priv->kms || !priv->kms->funcs->get_msm_mode)
|
||||||
msm_is_mode_seamless_vrr(&crtc_state->adjusted_mode) ||
|
return false;
|
||||||
msm_is_mode_seamless_poms(&crtc_state->adjusted_mode) ||
|
|
||||||
msm_is_mode_seamless_dyn_clk(&crtc_state->adjusted_mode))
|
msm_mode = priv->kms->funcs->get_msm_mode(crtc_state);
|
||||||
|
if (!msm_mode)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (msm_is_mode_seamless(msm_mode) ||
|
||||||
|
msm_is_mode_seamless_vrr(msm_mode) ||
|
||||||
|
msm_is_mode_seamless_poms(msm_mode) ||
|
||||||
|
msm_is_mode_seamless_dyn_clk(msm_mode))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (msm_is_mode_seamless_dms(&crtc_state->adjusted_mode) && !enable)
|
if (msm_is_mode_seamless_dms(msm_mode) && !enable)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!crtc_state->mode_changed && crtc_state->connectors_changed) {
|
if (!crtc_state->mode_changed && crtc_state->connectors_changed) {
|
||||||
@@ -71,6 +80,9 @@ static inline bool _msm_seamless_for_crtc(struct drm_atomic_state *state,
|
|||||||
static inline bool _msm_seamless_for_conn(struct drm_connector *connector,
|
static inline bool _msm_seamless_for_conn(struct drm_connector *connector,
|
||||||
struct drm_connector_state *old_conn_state, bool enable)
|
struct drm_connector_state *old_conn_state, bool enable)
|
||||||
{
|
{
|
||||||
|
struct msm_display_mode *msm_mode;
|
||||||
|
struct msm_drm_private *priv = connector->dev->dev_private;
|
||||||
|
|
||||||
if (!old_conn_state || !old_conn_state->crtc)
|
if (!old_conn_state || !old_conn_state->crtc)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -88,19 +100,17 @@ static inline bool _msm_seamless_for_conn(struct drm_connector *connector,
|
|||||||
old_conn_state->crtc->state->connectors_changed)
|
old_conn_state->crtc->state->connectors_changed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (msm_is_mode_seamless(&old_conn_state->crtc->state->mode))
|
if (!priv || !priv->kms || !priv->kms->funcs->get_msm_mode)
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
if (msm_is_mode_seamless_vrr(
|
msm_mode = priv->kms->funcs->get_msm_mode(old_conn_state->crtc->state);
|
||||||
&old_conn_state->crtc->state->adjusted_mode))
|
if (!msm_mode)
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
if (msm_is_mode_seamless_dyn_clk(
|
if (msm_is_mode_seamless(msm_mode) ||
|
||||||
&old_conn_state->crtc->state->adjusted_mode))
|
msm_is_mode_seamless_vrr(msm_mode) ||
|
||||||
return true;
|
msm_is_mode_seamless_dyn_clk(msm_mode) ||
|
||||||
|
msm_is_mode_seamless_dms(msm_mode))
|
||||||
if (msm_is_mode_seamless_dms(
|
|
||||||
&old_conn_state->crtc->state->adjusted_mode))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -359,6 +369,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
|||||||
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
|
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
|
||||||
new_crtc_state, i) {
|
new_crtc_state, i) {
|
||||||
const struct drm_crtc_helper_funcs *funcs;
|
const struct drm_crtc_helper_funcs *funcs;
|
||||||
|
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 (!drm_atomic_crtc_needs_modeset(new_crtc_state))
|
||||||
@@ -382,8 +393,14 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
|||||||
funcs->commit(crtc);
|
funcs->commit(crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msm_needs_vblank_pre_modeset(
|
if (!kms->funcs || !kms->funcs->get_msm_mode)
|
||||||
&new_crtc_state->adjusted_mode))
|
continue;
|
||||||
|
|
||||||
|
msm_mode = kms->funcs->get_msm_mode(new_crtc_state);
|
||||||
|
if (!msm_mode)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (msm_needs_vblank_pre_modeset(msm_mode))
|
||||||
drm_crtc_wait_one_vblank(crtc);
|
drm_crtc_wait_one_vblank(crtc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -295,6 +295,18 @@ enum panel_op_mode {
|
|||||||
MSM_DISPLAY_MODE_MAX,
|
MSM_DISPLAY_MODE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct msm_display_mode - wrapper for drm_display_mode
|
||||||
|
* @base: drm_display_mode attached to this msm_mode
|
||||||
|
* @private_flags: integer holding private driver mode flags
|
||||||
|
* @private: pointer to private driver information
|
||||||
|
*/
|
||||||
|
struct msm_display_mode {
|
||||||
|
struct drm_display_mode *base;
|
||||||
|
u32 private_flags;
|
||||||
|
u32 *private;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct msm_ratio - integer ratio
|
* struct msm_ratio - integer ratio
|
||||||
* @numer: numerator
|
* @numer: numerator
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -67,6 +67,8 @@ struct msm_kms_funcs {
|
|||||||
void (*commit)(struct msm_kms *kms, struct drm_atomic_state *state);
|
void (*commit)(struct msm_kms *kms, struct drm_atomic_state *state);
|
||||||
void (*complete_commit)(struct msm_kms *kms,
|
void (*complete_commit)(struct msm_kms *kms,
|
||||||
struct drm_atomic_state *state);
|
struct drm_atomic_state *state);
|
||||||
|
struct msm_display_mode *(*get_msm_mode)(
|
||||||
|
struct drm_crtc_state *c_state);
|
||||||
/* functions to wait for atomic commit completed on each CRTC */
|
/* functions to wait for atomic commit completed on each CRTC */
|
||||||
void (*wait_for_crtc_commit_done)(struct msm_kms *kms,
|
void (*wait_for_crtc_commit_done)(struct msm_kms *kms,
|
||||||
struct drm_crtc *crtc);
|
struct drm_crtc *crtc);
|
||||||
@@ -206,45 +208,45 @@ struct msm_kms *sde_kms_init(struct drm_device *dev);
|
|||||||
/**
|
/**
|
||||||
* Mode Set Utility Functions
|
* Mode Set Utility Functions
|
||||||
*/
|
*/
|
||||||
static inline bool msm_is_mode_seamless(const struct drm_display_mode *mode)
|
static inline bool msm_is_mode_seamless(const struct msm_display_mode *mode)
|
||||||
{
|
{
|
||||||
return (mode->private_flags & DRM_MODE_FLAG_SEAMLESS);
|
return (mode->private_flags & DRM_MODE_FLAG_SEAMLESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool msm_is_mode_seamless_dms(const struct drm_display_mode *mode)
|
static inline bool msm_is_mode_seamless_dms(const struct msm_display_mode *mode)
|
||||||
{
|
{
|
||||||
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_DMS)
|
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_DMS)
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool msm_is_mode_dynamic_fps(const struct drm_display_mode *mode)
|
static inline bool msm_is_mode_dynamic_fps(const struct msm_display_mode *mode)
|
||||||
{
|
{
|
||||||
return ((mode->private_flags & DRM_MODE_FLAG_SEAMLESS) &&
|
return ((mode->private_flags & DRM_MODE_FLAG_SEAMLESS) &&
|
||||||
(mode->private_flags & MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS));
|
(mode->private_flags & MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool msm_is_mode_seamless_vrr(const struct drm_display_mode *mode)
|
static inline bool msm_is_mode_seamless_vrr(const struct msm_display_mode *mode)
|
||||||
{
|
{
|
||||||
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_VRR)
|
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_VRR)
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool msm_is_mode_seamless_poms(
|
static inline bool msm_is_mode_seamless_poms(
|
||||||
const struct drm_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)
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool msm_is_mode_seamless_dyn_clk(
|
static inline bool msm_is_mode_seamless_dyn_clk(
|
||||||
const struct drm_display_mode *mode)
|
const struct msm_display_mode *mode)
|
||||||
{
|
{
|
||||||
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_DYN_CLK)
|
return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_DYN_CLK)
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool msm_needs_vblank_pre_modeset(
|
static inline bool msm_needs_vblank_pre_modeset(
|
||||||
const struct drm_display_mode *mode)
|
const struct msm_display_mode *mode)
|
||||||
{
|
{
|
||||||
return (mode->private_flags & MSM_MODE_FLAG_VBLANK_PRE_MODESET);
|
return (mode->private_flags & MSM_MODE_FLAG_VBLANK_PRE_MODESET);
|
||||||
}
|
}
|
||||||
|
@@ -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:%d] " fmt, __func__, __LINE__
|
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
|
||||||
@@ -421,6 +421,22 @@ static void sde_connector_get_avail_res_info(struct drm_connector *conn,
|
|||||||
avail_res->max_mixer_width = sde_kms->catalog->max_mixer_width;
|
avail_res->max_mixer_width = sde_kms->catalog->max_mixer_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sde_connector_set_msm_mode(struct drm_connector_state *conn_state,
|
||||||
|
struct drm_display_mode *adj_mode)
|
||||||
|
{
|
||||||
|
struct sde_connector_state *c_state;
|
||||||
|
|
||||||
|
c_state = to_sde_connector_state(conn_state);
|
||||||
|
if (!c_state || !adj_mode) {
|
||||||
|
SDE_ERROR("invalid params c_state: %d, adj_mode %d\n",
|
||||||
|
c_state == NULL, adj_mode == NULL);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
c_state->msm_mode.base = adj_mode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sde_connector_get_mode_info(struct drm_connector *conn,
|
int sde_connector_get_mode_info(struct drm_connector *conn,
|
||||||
const struct drm_display_mode *drm_mode,
|
const struct drm_display_mode *drm_mode,
|
||||||
struct msm_mode_info *mode_info)
|
struct msm_mode_info *mode_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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SDE_CONNECTOR_H_
|
#ifndef _SDE_CONNECTOR_H_
|
||||||
@@ -612,6 +612,7 @@ struct sde_connector {
|
|||||||
* @mode_info: local copy of msm_mode_info struct
|
* @mode_info: local copy of msm_mode_info struct
|
||||||
* @hdr_meta: HDR metadata info passed from userspace
|
* @hdr_meta: HDR metadata info passed from userspace
|
||||||
* @dyn_hdr_meta: Dynamic HDR metadata payload and state tracking
|
* @dyn_hdr_meta: Dynamic HDR metadata payload and state tracking
|
||||||
|
* @msm_mode: struct containing drm_mode and downstream private variables
|
||||||
* @old_topology_name: topology of previous atomic state. remove this in later
|
* @old_topology_name: topology of previous atomic state. remove this in later
|
||||||
* kernel versions which provide drm_atomic_state old_state pointers
|
* kernel versions which provide drm_atomic_state old_state pointers
|
||||||
*/
|
*/
|
||||||
@@ -626,6 +627,7 @@ struct sde_connector_state {
|
|||||||
struct msm_mode_info mode_info;
|
struct msm_mode_info mode_info;
|
||||||
struct drm_msm_ext_hdr_metadata hdr_meta;
|
struct drm_msm_ext_hdr_metadata hdr_meta;
|
||||||
struct sde_connector_dyn_hdr_metadata dyn_hdr_meta;
|
struct sde_connector_dyn_hdr_metadata dyn_hdr_meta;
|
||||||
|
struct msm_display_mode msm_mode;
|
||||||
enum sde_rm_topology_name old_topology_name;
|
enum sde_rm_topology_name old_topology_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1026,6 +1028,15 @@ static inline int sde_connector_state_get_compression_info(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_connector_set_msm_mode - set msm_mode for connector state
|
||||||
|
* @conn_state: Pointer to drm connector state structure
|
||||||
|
* @adj_mode: Pointer to adjusted display mode for display
|
||||||
|
* Returns: Zero on success
|
||||||
|
*/
|
||||||
|
int sde_connector_set_msm_mode(struct drm_connector_state *conn_state,
|
||||||
|
struct drm_display_mode *adj_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_connector_get_mode_info - retrieve mode info for given mode
|
* sde_connector_get_mode_info - retrieve mode info for given mode
|
||||||
* @connector: Pointer to drm connector structure
|
* @connector: Pointer to drm connector structure
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "sde_power_handle.h"
|
#include "sde_power_handle.h"
|
||||||
#include "sde_core_perf.h"
|
#include "sde_core_perf.h"
|
||||||
#include "sde_trace.h"
|
#include "sde_trace.h"
|
||||||
|
#include "msm_drv.h"
|
||||||
|
|
||||||
#define SDE_PSTATES_MAX (SDE_STAGE_MAX * 4)
|
#define SDE_PSTATES_MAX (SDE_STAGE_MAX * 4)
|
||||||
#define SDE_MULTIRECT_PLANE_MAX (SDE_STAGE_MAX * 2)
|
#define SDE_MULTIRECT_PLANE_MAX (SDE_STAGE_MAX * 2)
|
||||||
@@ -455,15 +456,83 @@ static void sde_crtc_destroy(struct drm_crtc *crtc)
|
|||||||
kfree(sde_crtc);
|
kfree(sde_crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct msm_display_mode *sde_crtc_get_msm_mode(struct drm_crtc_state *c_state)
|
||||||
|
{
|
||||||
|
struct drm_connector *connector;
|
||||||
|
struct drm_encoder *encoder;
|
||||||
|
struct sde_connector_state *conn_state;
|
||||||
|
bool encoder_valid = false;
|
||||||
|
|
||||||
|
drm_for_each_encoder_mask(encoder, c_state->crtc->dev,
|
||||||
|
c_state->encoder_mask) {
|
||||||
|
if (!sde_encoder_in_clone_mode(encoder)) {
|
||||||
|
encoder_valid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!encoder_valid)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
connector = sde_encoder_get_connector(c_state->crtc->dev, encoder);
|
||||||
|
if (!connector)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
conn_state = to_sde_connector_state(connector->state);
|
||||||
|
if (!conn_state)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &conn_state->msm_mode;
|
||||||
|
}
|
||||||
|
|
||||||
static bool sde_crtc_mode_fixup(struct drm_crtc *crtc,
|
static bool sde_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||||
const struct drm_display_mode *mode,
|
const struct drm_display_mode *mode,
|
||||||
struct drm_display_mode *adjusted_mode)
|
struct drm_display_mode *adjusted_mode)
|
||||||
{
|
{
|
||||||
|
struct msm_display_mode *msm_mode;
|
||||||
|
struct drm_crtc_state *c_state;
|
||||||
|
struct drm_connector *connector;
|
||||||
|
struct drm_encoder *encoder;
|
||||||
|
struct drm_connector_state *new_conn_state;
|
||||||
|
struct sde_connector_state *c_conn_state;
|
||||||
|
bool encoder_valid = false;
|
||||||
|
int i;
|
||||||
|
|
||||||
SDE_DEBUG("\n");
|
SDE_DEBUG("\n");
|
||||||
|
|
||||||
if ((msm_is_mode_seamless(adjusted_mode) ||
|
c_state = container_of(adjusted_mode, struct drm_crtc_state,
|
||||||
(msm_is_mode_seamless_vrr(adjusted_mode) ||
|
adjusted_mode);
|
||||||
msm_is_mode_seamless_dyn_clk(adjusted_mode))) &&
|
|
||||||
|
drm_for_each_encoder_mask(encoder, c_state->crtc->dev,
|
||||||
|
c_state->encoder_mask) {
|
||||||
|
if (!sde_encoder_in_clone_mode(encoder)) {
|
||||||
|
encoder_valid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!encoder_valid) {
|
||||||
|
SDE_ERROR("encoder not found\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_new_connector_in_state(c_state->state, connector,
|
||||||
|
new_conn_state, i) {
|
||||||
|
if (new_conn_state->best_encoder == encoder){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c_conn_state = to_sde_connector_state(new_conn_state);
|
||||||
|
if (!c_conn_state) {
|
||||||
|
SDE_ERROR("could not get connector state\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
msm_mode = &c_conn_state->msm_mode;
|
||||||
|
if ((msm_is_mode_seamless(msm_mode) ||
|
||||||
|
(msm_is_mode_seamless_vrr(msm_mode) ||
|
||||||
|
msm_is_mode_seamless_dyn_clk(msm_mode))) &&
|
||||||
(!crtc->enabled)) {
|
(!crtc->enabled)) {
|
||||||
SDE_ERROR("crtc state prevents seamless transition\n");
|
SDE_ERROR("crtc state prevents seamless transition\n");
|
||||||
return false;
|
return false;
|
||||||
@@ -4266,6 +4335,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
|
|||||||
u32 power_on;
|
u32 power_on;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
struct sde_crtc_state *cstate;
|
struct sde_crtc_state *cstate;
|
||||||
|
struct msm_display_mode *msm_mode;
|
||||||
|
|
||||||
if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
|
if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
|
||||||
SDE_ERROR("invalid crtc\n");
|
SDE_ERROR("invalid crtc\n");
|
||||||
@@ -4302,12 +4372,17 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
|
|||||||
* change is also consider to enable/disable UIDLE
|
* change is also consider to enable/disable UIDLE
|
||||||
*/
|
*/
|
||||||
sde_core_perf_crtc_update_uidle(crtc, true);
|
sde_core_perf_crtc_update_uidle(crtc, true);
|
||||||
|
msm_mode = sde_crtc_get_msm_mode(crtc->state);
|
||||||
|
if (!msm_mode){
|
||||||
|
SDE_ERROR("invalid msm mode, %s\n",
|
||||||
|
crtc->state->adjusted_mode.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* return early if crtc is already enabled, do this after UIDLE check */
|
/* return early if crtc is already enabled, do this after UIDLE check */
|
||||||
if (sde_crtc->enabled) {
|
if (sde_crtc->enabled) {
|
||||||
if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode) ||
|
if (msm_is_mode_seamless_dms(msm_mode) ||
|
||||||
msm_is_mode_seamless_dyn_clk(&crtc->state->adjusted_mode))
|
msm_is_mode_seamless_dyn_clk(msm_mode))
|
||||||
|
|
||||||
SDE_DEBUG("%s extra crtc enable expected during DMS\n",
|
SDE_DEBUG("%s extra crtc enable expected during DMS\n",
|
||||||
sde_crtc->name);
|
sde_crtc->name);
|
||||||
else
|
else
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -588,6 +588,13 @@ static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc)
|
|||||||
*/
|
*/
|
||||||
int sde_crtc_vblank(struct drm_crtc *crtc, bool en);
|
int sde_crtc_vblank(struct drm_crtc *crtc, bool en);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_crtc_get_msm_mode - get msm_mode for a given crtc state
|
||||||
|
* @c_state: Pointer to drm crtc state object
|
||||||
|
* Returns: msm_display_mode corresponding to this crtc state, or NULL if none
|
||||||
|
*/
|
||||||
|
struct msm_display_mode *sde_crtc_get_msm_mode(struct drm_crtc_state *c_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_crtc_commit_kickoff - trigger kickoff of the commit for this crtc
|
* sde_crtc_commit_kickoff - trigger kickoff of the commit for this crtc
|
||||||
* @crtc: Pointer to drm crtc object
|
* @crtc: Pointer to drm crtc object
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -961,6 +961,9 @@ static int sde_encoder_virt_atomic_check(
|
|||||||
sde_conn = to_sde_connector(conn_state->connector);
|
sde_conn = to_sde_connector(conn_state->connector);
|
||||||
sde_conn_state = to_sde_connector_state(conn_state);
|
sde_conn_state = to_sde_connector_state(conn_state);
|
||||||
sde_crtc_state = to_sde_crtc_state(crtc_state);
|
sde_crtc_state = to_sde_crtc_state(crtc_state);
|
||||||
|
ret = sde_connector_set_msm_mode(conn_state, adj_mode);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
SDE_EVT32(DRMID(drm_enc), crtc_state->mode_changed,
|
SDE_EVT32(DRMID(drm_enc), crtc_state->mode_changed,
|
||||||
crtc_state->active_changed, crtc_state->connectors_changed);
|
crtc_state->active_changed, crtc_state->connectors_changed);
|
||||||
@@ -1006,18 +1009,18 @@ static int sde_encoder_virt_atomic_check(
|
|||||||
CONNECTOR_PROP_QSYNC_MODE);
|
CONNECTOR_PROP_QSYNC_MODE);
|
||||||
|
|
||||||
if (has_modeset && qsync_dirty &&
|
if (has_modeset && qsync_dirty &&
|
||||||
(msm_is_mode_seamless_poms(adj_mode) ||
|
(msm_is_mode_seamless_poms(&sde_conn_state->msm_mode) ||
|
||||||
msm_is_mode_seamless_dms(adj_mode) ||
|
msm_is_mode_seamless_dms(&sde_conn_state->msm_mode) ||
|
||||||
msm_is_mode_seamless_dyn_clk(adj_mode))) {
|
msm_is_mode_seamless_dyn_clk(&sde_conn_state->msm_mode))) {
|
||||||
SDE_ERROR("invalid qsync update during modeset priv flag:%x\n",
|
SDE_ERROR("invalid qsync update during modeset priv flag:%x\n",
|
||||||
adj_mode->private_flags);
|
sde_conn_state->msm_mode.private_flags);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDE_EVT32(DRMID(drm_enc), adj_mode->flags, adj_mode->private_flags,
|
SDE_EVT32(DRMID(drm_enc), adj_mode->flags,
|
||||||
|
sde_conn_state->msm_mode.private_flags,
|
||||||
old_top, adj_mode->vrefresh, adj_mode->hdisplay,
|
old_top, adj_mode->vrefresh, adj_mode->hdisplay,
|
||||||
adj_mode->vdisplay, adj_mode->htotal, adj_mode->vtotal);
|
adj_mode->vdisplay, adj_mode->htotal, adj_mode->vtotal);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2095,7 +2098,7 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sde_encoder_virt_mode_switch(struct drm_encoder *drm_enc,
|
static void sde_encoder_virt_mode_switch(struct drm_encoder *drm_enc,
|
||||||
enum sde_intf_mode intf_mode, struct drm_display_mode *adj_mode)
|
enum sde_intf_mode intf_mode, struct msm_display_mode *adj_mode)
|
||||||
{
|
{
|
||||||
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);
|
||||||
@@ -2112,19 +2115,21 @@ static void sde_encoder_virt_mode_switch(struct drm_encoder *drm_enc,
|
|||||||
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, adj_mode->flags,
|
SDE_EVT32(DRMID(&sde_enc->base), intf_mode,
|
||||||
adj_mode->private_flags, SDE_EVTLOG_FUNC_CASE1);
|
adj_mode->base->flags, adj_mode->private_flags,
|
||||||
|
SDE_EVTLOG_FUNC_CASE1);
|
||||||
} else if (intf_mode == INTF_MODE_VIDEO) {
|
} 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, adj_mode->flags,
|
SDE_EVT32(DRMID(&sde_enc->base), intf_mode,
|
||||||
adj_mode->private_flags, SDE_EVTLOG_FUNC_CASE2);
|
adj_mode->base->flags, adj_mode->private_flags,
|
||||||
|
SDE_EVTLOG_FUNC_CASE2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drm_connector *_sde_encoder_get_connector(
|
struct drm_connector *sde_encoder_get_connector(
|
||||||
struct drm_device *dev, struct drm_encoder *drm_enc)
|
struct drm_device *dev, struct drm_encoder *drm_enc)
|
||||||
{
|
{
|
||||||
struct drm_connector_list_iter conn_iter;
|
struct drm_connector_list_iter conn_iter;
|
||||||
@@ -2227,7 +2232,7 @@ static bool sde_encoder_detect_panel_mode_switch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 drm_display_mode *adj_mode, bool pre_modeset)
|
struct msm_display_mode *msm_mode, bool pre_modeset)
|
||||||
{
|
{
|
||||||
struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
|
struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
|
||||||
enum sde_intf_mode intf_mode;
|
enum sde_intf_mode intf_mode;
|
||||||
@@ -2239,8 +2244,8 @@ static int sde_encoder_virt_modeset_rc(struct drm_encoder *drm_enc,
|
|||||||
|
|
||||||
if (pre_modeset) {
|
if (pre_modeset) {
|
||||||
intf_mode = sde_encoder_get_intf_mode(drm_enc);
|
intf_mode = sde_encoder_get_intf_mode(drm_enc);
|
||||||
if (msm_is_mode_seamless_dms(adj_mode) ||
|
if (msm_is_mode_seamless_dms(msm_mode) ||
|
||||||
(msm_is_mode_seamless_dyn_clk(adj_mode) &&
|
(msm_is_mode_seamless_dyn_clk(msm_mode) &&
|
||||||
is_cmd_mode)) {
|
is_cmd_mode)) {
|
||||||
/* restore resource state before releasing them */
|
/* restore resource state before releasing them */
|
||||||
ret = sde_encoder_resource_control(drm_enc,
|
ret = sde_encoder_resource_control(drm_enc,
|
||||||
@@ -2257,20 +2262,20 @@ 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(adj_mode,
|
} else if (sde_encoder_detect_panel_mode_switch(msm_mode->base,
|
||||||
intf_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,
|
||||||
adj_mode);
|
msm_mode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (msm_is_mode_seamless_dms(adj_mode) ||
|
if (msm_is_mode_seamless_dms(msm_mode) ||
|
||||||
(msm_is_mode_seamless_dyn_clk(adj_mode) &&
|
(msm_is_mode_seamless_dyn_clk(msm_mode) &&
|
||||||
is_cmd_mode))
|
is_cmd_mode))
|
||||||
sde_encoder_resource_control(&sde_enc->base,
|
sde_encoder_resource_control(&sde_enc->base,
|
||||||
SDE_ENC_RC_EVENT_POST_MODESET);
|
SDE_ENC_RC_EVENT_POST_MODESET);
|
||||||
else if (msm_is_mode_seamless_poms(adj_mode))
|
else if (msm_is_mode_seamless_poms(msm_mode))
|
||||||
_sde_encoder_modeset_helper_locked(drm_enc,
|
_sde_encoder_modeset_helper_locked(drm_enc,
|
||||||
SDE_ENC_RC_EVENT_POST_MODESET);
|
SDE_ENC_RC_EVENT_POST_MODESET);
|
||||||
}
|
}
|
||||||
@@ -2285,6 +2290,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
|||||||
struct sde_encoder_virt *sde_enc;
|
struct sde_encoder_virt *sde_enc;
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
struct drm_connector *conn;
|
struct drm_connector *conn;
|
||||||
|
struct sde_connector_state *c_state;
|
||||||
|
struct msm_display_mode *msm_mode;
|
||||||
int i = 0, ret;
|
int i = 0, ret;
|
||||||
int num_lm, num_intf, num_pp_per_intf;
|
int num_lm, num_intf, num_pp_per_intf;
|
||||||
|
|
||||||
@@ -2319,7 +2326,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
|||||||
sde_crtc_set_qos_dirty(drm_enc->crtc);
|
sde_crtc_set_qos_dirty(drm_enc->crtc);
|
||||||
|
|
||||||
/* get and store the mode_info */
|
/* get and store the mode_info */
|
||||||
conn = _sde_encoder_get_connector(sde_kms->dev, drm_enc);
|
conn = sde_encoder_get_connector(sde_kms->dev, drm_enc);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n");
|
SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n");
|
||||||
return;
|
return;
|
||||||
@@ -2330,9 +2337,15 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
|||||||
|
|
||||||
sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info);
|
sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info);
|
||||||
sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc);
|
sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc);
|
||||||
|
c_state = to_sde_connector_state(conn->state);
|
||||||
|
if (!c_state) {
|
||||||
|
SDE_ERROR_ENC(sde_enc, "could not get connector state");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* release resources before seamless mode change */
|
/* release resources before seamless mode change */
|
||||||
ret = sde_encoder_virt_modeset_rc(drm_enc, adj_mode, true);
|
msm_mode = &c_state->msm_mode;
|
||||||
|
ret = sde_encoder_virt_modeset_rc(drm_enc, msm_mode, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2374,7 +2387,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* update resources after seamless mode change */
|
/* update resources after seamless mode change */
|
||||||
sde_encoder_virt_modeset_rc(drm_enc, adj_mode, false);
|
sde_encoder_virt_modeset_rc(drm_enc, msm_mode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable)
|
void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable)
|
||||||
@@ -2694,8 +2707,10 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
|
|||||||
{
|
{
|
||||||
struct sde_encoder_virt *sde_enc = NULL;
|
struct sde_encoder_virt *sde_enc = NULL;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
struct sde_connector_state *c_state;
|
||||||
struct msm_compression_info *comp_info = NULL;
|
struct msm_compression_info *comp_info = NULL;
|
||||||
struct drm_display_mode *cur_mode = NULL;
|
struct drm_display_mode *cur_mode = NULL;
|
||||||
|
struct msm_display_mode *msm_mode;
|
||||||
struct msm_display_info *disp_info;
|
struct msm_display_info *disp_info;
|
||||||
|
|
||||||
if (!drm_enc || !drm_enc->crtc) {
|
if (!drm_enc || !drm_enc->crtc) {
|
||||||
@@ -2736,12 +2751,18 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sde_encoder_input_handler_register(drm_enc);
|
_sde_encoder_input_handler_register(drm_enc);
|
||||||
|
c_state = to_sde_connector_state(sde_enc->cur_master->connector->state);
|
||||||
|
if (!c_state) {
|
||||||
|
SDE_ERROR("invalid connector state\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
msm_mode = &c_state->msm_mode;
|
||||||
if ((drm_enc->crtc->state->connectors_changed &&
|
if ((drm_enc->crtc->state->connectors_changed &&
|
||||||
sde_encoder_in_clone_mode(drm_enc)) ||
|
sde_encoder_in_clone_mode(drm_enc)) ||
|
||||||
!(msm_is_mode_seamless_vrr(cur_mode)
|
!(msm_is_mode_seamless_vrr(msm_mode)
|
||||||
|| msm_is_mode_seamless_dms(cur_mode)
|
|| msm_is_mode_seamless_dms(msm_mode)
|
||||||
|| msm_is_mode_seamless_dyn_clk(cur_mode)))
|
|| msm_is_mode_seamless_dyn_clk(msm_mode)))
|
||||||
kthread_init_delayed_work(&sde_enc->delayed_off_work,
|
kthread_init_delayed_work(&sde_enc->delayed_off_work,
|
||||||
sde_encoder_off_work);
|
sde_encoder_off_work);
|
||||||
|
|
||||||
@@ -2785,8 +2806,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
|
|||||||
* already. Invoke restore to reconfigure the
|
* already. Invoke restore to reconfigure the
|
||||||
* new mode.
|
* new mode.
|
||||||
*/
|
*/
|
||||||
if ((msm_is_mode_seamless_dms(cur_mode) ||
|
if ((msm_is_mode_seamless_dms(msm_mode) ||
|
||||||
msm_is_mode_seamless_dyn_clk(cur_mode)) &&
|
msm_is_mode_seamless_dyn_clk(msm_mode)) &&
|
||||||
phys->ops.restore)
|
phys->ops.restore)
|
||||||
phys->ops.restore(phys);
|
phys->ops.restore(phys);
|
||||||
else if (phys->ops.enable)
|
else if (phys->ops.enable)
|
||||||
@@ -2799,8 +2820,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
|
|||||||
sde_enc->misr_frame_count);
|
sde_enc->misr_frame_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((msm_is_mode_seamless_dms(cur_mode) ||
|
if ((msm_is_mode_seamless_dms(msm_mode) ||
|
||||||
msm_is_mode_seamless_dyn_clk(cur_mode)) &&
|
msm_is_mode_seamless_dyn_clk(msm_mode)) &&
|
||||||
sde_enc->cur_master->ops.restore)
|
sde_enc->cur_master->ops.restore)
|
||||||
sde_enc->cur_master->ops.restore(sde_enc->cur_master);
|
sde_enc->cur_master->ops.restore(sde_enc->cur_master);
|
||||||
else if (sde_enc->cur_master->ops.enable)
|
else if (sde_enc->cur_master->ops.enable)
|
||||||
@@ -5285,9 +5306,9 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drm_mode = &encoder->crtc->state->adjusted_mode;
|
||||||
ret = sde_connector_get_mode_info(&sde_conn->base,
|
ret = sde_connector_get_mode_info(&sde_conn->base,
|
||||||
&encoder->crtc->state->adjusted_mode,
|
drm_mode, &sde_conn_state->mode_info);
|
||||||
&sde_conn_state->mode_info);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
SDE_ERROR_ENC(sde_enc,
|
SDE_ERROR_ENC(sde_enc,
|
||||||
"conn: ->get_mode_info failed. ret=%d\n", ret);
|
"conn: ->get_mode_info failed. ret=%d\n", ret);
|
||||||
@@ -5314,7 +5335,6 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder,
|
|||||||
|
|
||||||
SDE_DEBUG_ENC(sde_enc, "connector topology = %llu\n",
|
SDE_DEBUG_ENC(sde_enc, "connector topology = %llu\n",
|
||||||
sde_connector_get_topology_name(conn));
|
sde_connector_get_topology_name(conn));
|
||||||
drm_mode = &encoder->crtc->state->adjusted_mode;
|
|
||||||
SDE_DEBUG_ENC(sde_enc, "hdisplay = %d, vdisplay = %d\n",
|
SDE_DEBUG_ENC(sde_enc, "hdisplay = %d, vdisplay = %d\n",
|
||||||
drm_mode->hdisplay, drm_mode->vdisplay);
|
drm_mode->hdisplay, drm_mode->vdisplay);
|
||||||
drm_set_preferred_mode(conn, drm_mode->hdisplay, drm_mode->vdisplay);
|
drm_set_preferred_mode(conn, drm_mode->hdisplay, drm_mode->vdisplay);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -559,6 +559,14 @@ void sde_encoder_uidle_enable(struct drm_encoder *drm_enc, bool enable);
|
|||||||
*/
|
*/
|
||||||
void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable);
|
void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable);
|
||||||
|
|
||||||
|
/**sde_encoder_get_connector - get connector corresponding to encoder
|
||||||
|
* @dev: Pointer to drm device structure
|
||||||
|
* @drm_enc: Pointer to drm encoder structure
|
||||||
|
* Returns: drm connector if found, null if not found
|
||||||
|
*/
|
||||||
|
struct drm_connector *sde_encoder_get_connector(struct drm_device *dev,
|
||||||
|
struct drm_encoder *drm_enc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sde_encoder_get_dfps_maxfps - get dynamic FPS max frame rate of
|
* sde_encoder_get_dfps_maxfps - get dynamic FPS max frame rate of
|
||||||
the given encoder
|
the given encoder
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
|
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
|
||||||
@@ -1152,23 +1152,25 @@ static void sde_encoder_phys_vid_handle_post_kickoff(
|
|||||||
static void sde_encoder_phys_vid_prepare_for_commit(
|
static void sde_encoder_phys_vid_prepare_for_commit(
|
||||||
struct sde_encoder_phys *phys_enc)
|
struct sde_encoder_phys *phys_enc)
|
||||||
{
|
{
|
||||||
struct drm_crtc *crtc;
|
struct sde_connector_state *c_state;
|
||||||
|
|
||||||
if (!phys_enc || !phys_enc->parent) {
|
if (!phys_enc || !phys_enc->parent) {
|
||||||
SDE_ERROR("invalid encoder parameters\n");
|
SDE_ERROR("invalid encoder parameters\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
crtc = phys_enc->parent->crtc;
|
if (phys_enc->connector && phys_enc->connector->state) {
|
||||||
if (!crtc || !crtc->state) {
|
c_state = to_sde_connector_state(phys_enc->connector->state);
|
||||||
SDE_ERROR("invalid crtc state\n");
|
if (!c_state) {
|
||||||
|
SDE_ERROR("invalid connector state\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)
|
if (!msm_is_mode_seamless_vrr(&c_state->msm_mode)
|
||||||
&& sde_connector_is_qsync_updated(phys_enc->connector))
|
&& sde_connector_is_qsync_updated(phys_enc->connector))
|
||||||
_sde_encoder_phys_vid_avr_ctrl(phys_enc);
|
_sde_encoder_phys_vid_avr_ctrl(phys_enc);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sde_encoder_phys_vid_irq_control(struct sde_encoder_phys *phys_enc,
|
static void sde_encoder_phys_vid_irq_control(struct sde_encoder_phys *phys_enc,
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -3507,6 +3507,11 @@ static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms,
|
|||||||
kthread_flush_worker(&priv->pp_event_worker);
|
kthread_flush_worker(&priv->pp_event_worker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct msm_display_mode *sde_kms_get_msm_mode(struct drm_crtc_state *c_state)
|
||||||
|
{
|
||||||
|
return sde_crtc_get_msm_mode(c_state);
|
||||||
|
}
|
||||||
|
|
||||||
static int sde_kms_pm_suspend(struct device *dev)
|
static int sde_kms_pm_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct drm_device *ddev;
|
struct drm_device *ddev;
|
||||||
@@ -3726,6 +3731,7 @@ static const struct msm_kms_funcs kms_funcs = {
|
|||||||
.prepare_commit = sde_kms_prepare_commit,
|
.prepare_commit = sde_kms_prepare_commit,
|
||||||
.commit = sde_kms_commit,
|
.commit = sde_kms_commit,
|
||||||
.complete_commit = sde_kms_complete_commit,
|
.complete_commit = sde_kms_complete_commit,
|
||||||
|
.get_msm_mode = sde_kms_get_msm_mode,
|
||||||
.wait_for_crtc_commit_done = sde_kms_wait_for_commit_done,
|
.wait_for_crtc_commit_done = sde_kms_wait_for_commit_done,
|
||||||
.wait_for_tx_complete = sde_kms_wait_for_frame_transfer_complete,
|
.wait_for_tx_complete = sde_kms_wait_for_frame_transfer_complete,
|
||||||
.check_modified_format = sde_format_check_modified_format,
|
.check_modified_format = sde_format_check_modified_format,
|
||||||
|
Reference in New Issue
Block a user