Merge 5a5adbba9f on remote branch

Change-Id: I82779224a7c3752c42974842515efd6e06acdfd7
This commit is contained in:
Linux Build Service Account
2022-08-19 15:24:37 -07:00
21 changed files with 273 additions and 72 deletions

View File

@@ -202,6 +202,7 @@ struct dp_display_private {
struct work_struct connect_work;
struct work_struct attention_work;
struct mutex session_lock;
struct mutex accounting_lock;
bool hdcp_delayed_off;
bool no_aux_switch;
@@ -209,6 +210,7 @@ struct dp_display_private {
struct dp_mst mst;
u32 tot_dsc_blks_in_use;
u32 tot_lm_blks_in_use;
bool process_hpd_connect;
struct dev_pm_qos_request pm_qos_req[NR_CPUS];
@@ -1483,6 +1485,25 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
return 0;
}
static void dp_display_clear_reservation(struct dp_display *dp, struct dp_panel *panel)
{
struct dp_display_private *dp_display;
if (!dp || !panel) {
DP_ERR("invalid params\n");
return;
}
dp_display = container_of(dp, struct dp_display_private, dp_display);
mutex_lock(&dp_display->accounting_lock);
dp_display->tot_lm_blks_in_use -= panel->max_lm;
panel->max_lm = 0;
mutex_unlock(&dp_display->accounting_lock);
}
static void dp_display_clear_dsc_resources(struct dp_display_private *dp,
struct dp_panel *panel)
{
@@ -1562,6 +1583,7 @@ static void dp_display_clean(struct dp_display_private *dp)
dp_display_stream_pre_disable(dp, dp_panel);
dp_display_stream_disable(dp, dp_panel);
dp_display_clear_reservation(&dp->dp_display, dp_panel);
dp_panel->deinit(dp_panel, 0);
}
@@ -1589,6 +1611,8 @@ static int dp_display_handle_disconnect(struct dp_display_private *dp)
dp_display_host_unready(dp);
dp->tot_lm_blks_in_use = 0;
mutex_unlock(&dp->session_lock);
SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state);
@@ -2002,6 +2026,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
};
mutex_init(&dp->session_lock);
mutex_init(&dp->accounting_lock);
dp->parser = dp_parser_get(dp->pdev);
if (IS_ERR(dp->parser)) {
@@ -2172,6 +2197,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
dp->cached_connector_status = connector_status_disconnected;
dp->tot_dsc_blks_in_use = 0;
dp->tot_lm_blks_in_use = 0;
dp->debug->hdcp_disabled = hdcp_disabled;
dp_display_update_hdcp_status(dp, true);
@@ -2575,6 +2601,7 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
dp_panel->audio->on(dp_panel->audio);
}
dp->aux->state &= ~DP_STATE_CTRL_POWERED_OFF;
dp->aux->state |= DP_STATE_CTRL_POWERED_ON;
complete_all(&dp->notification_comp);
DP_DEBUG("display post enable complete. state: 0x%x\n", dp->state);
@@ -2799,13 +2826,17 @@ static int dp_display_unprepare(struct dp_display *dp_display, void *panel)
}
dp_display_state_remove(DP_STATE_ENABLED);
dp->aux->state = DP_STATE_CTRL_POWERED_OFF;
dp->aux->state &= ~DP_STATE_CTRL_POWERED_ON;
dp->aux->state |= DP_STATE_CTRL_POWERED_OFF;
complete_all(&dp->notification_comp);
/* log this as it results from user action of cable dis-connection */
DP_INFO("[OK]\n");
end:
dp->tot_lm_blks_in_use -= dp_panel->max_lm;
dp_panel->max_lm = 0;
dp_panel->deinit(dp_panel, flags);
mutex_unlock(&dp->session_lock);
SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state);
@@ -2864,11 +2895,14 @@ static int dp_display_validate_topology(struct dp_display_private *dp,
u32 num_lm = 0, num_dsc = 0, num_3dmux = 0;
bool dsc_capable = dp_mode->capabilities & DP_PANEL_CAPS_DSC;
u32 fps = dp_mode->timing.refresh_rate;
int avail_lm = 0;
mutex_lock(&dp->accounting_lock);
rc = msm_get_mixer_count(priv, mode, avail_res, &num_lm);
if (rc) {
DP_ERR("error getting mixer count. rc:%d\n", rc);
return rc;
goto end;
}
/* Merge using DSC, if enabled */
@@ -2876,7 +2910,7 @@ static int dp_display_validate_topology(struct dp_display_private *dp,
rc = msm_get_dsc_count(priv, mode->hdisplay, &num_dsc);
if (rc) {
DP_ERR("error getting dsc count. rc:%d\n", rc);
return rc;
goto end;
}
num_dsc = max(num_lm, num_dsc);
@@ -2886,7 +2920,8 @@ static int dp_display_validate_topology(struct dp_display_private *dp,
avail_res->num_lm);
/* Clear DSC caps and retry */
dp_mode->capabilities &= ~DP_PANEL_CAPS_DSC;
return -EAGAIN;
rc = -EAGAIN;
goto end;
} else {
/* Only DSCMERGE is supported on DP */
num_lm = num_dsc;
@@ -2897,24 +2932,36 @@ static int dp_display_validate_topology(struct dp_display_private *dp,
num_3dmux = 1;
}
if (num_lm > avail_res->num_lm) {
avail_lm = avail_res->num_lm + avail_res->num_lm_in_use - dp->tot_lm_blks_in_use;
if ((num_lm > dp_panel->max_lm) && (num_lm > avail_lm)) {
DP_DEBUG("mode %sx%d is invalid, not enough lm %d %d\n",
mode->name, fps, num_lm, num_lm, avail_res->num_lm);
return -EPERM;
mode->name, fps, num_lm, avail_res->num_lm);
rc = -EPERM;
goto end;
} else if (!num_dsc && (num_lm == dual && !num_3dmux)) {
DP_DEBUG("mode %sx%d is invalid, not enough 3dmux %d %d\n",
mode->name, fps, num_3dmux, avail_res->num_3dmux);
return -EPERM;
rc = -EPERM;
goto end;
} else if (num_lm == quad && num_dsc != quad) {
DP_DEBUG("mode %sx%d is invalid, unsupported DP topology lm:%d dsc:%d\n",
mode->name, fps, num_lm, num_dsc);
return -EPERM;
rc = -EPERM;
goto end;
}
DP_DEBUG_V("mode %sx%d is valid, supported DP topology lm:%d dsc:%d 3dmux:%d\n",
mode->name, fps, num_lm, num_dsc, num_3dmux);
return 0;
dp->tot_lm_blks_in_use -= dp_panel->max_lm;
dp_panel->max_lm = num_lm > avail_res->num_lm_in_use ? max(dp_panel->max_lm, num_lm) : 0;
dp->tot_lm_blks_in_use += dp_panel->max_lm;
rc = 0;
end:
mutex_unlock(&dp->accounting_lock);
return rc;
}
static enum drm_mode_status dp_display_validate_mode(
@@ -2970,6 +3017,8 @@ static enum drm_mode_status dp_display_validate_mode(
mode_status = MODE_OK;
end:
if (mode_status != MODE_OK)
dp_display_clear_reservation(dp_display, dp_panel);
mutex_unlock(&dp->session_lock);
DP_DEBUG_V("[%s] mode is %s\n", mode->name,
@@ -3642,6 +3691,7 @@ static int dp_display_probe(struct platform_device *pdev)
g_dp_display->set_colorspace = dp_display_setup_colospace;
g_dp_display->get_available_dp_resources =
dp_display_get_available_dp_resources;
g_dp_display->clear_reservation = dp_display_clear_reservation;
rc = component_add(&pdev->dev, &dp_display_comp_ops);
if (rc) {

View File

@@ -105,6 +105,7 @@ struct dp_display {
int (*get_available_dp_resources)(struct dp_display *dp_display,
const struct msm_resource_caps_info *avail_res,
struct msm_resource_caps_info *max_dp_avail_res);
void (*clear_reservation)(struct dp_display *dp, struct dp_panel *panel);
};
void *get_ipc_log_context(void);

View File

@@ -257,6 +257,8 @@ static void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
dp->convert_to_dp_mode(dp, bridge->dp_panel, adjusted_mode,
&bridge->dp_mode);
dp->clear_reservation(dp, bridge->dp_panel);
}
static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge,
@@ -290,6 +292,7 @@ static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge,
dp = bridge->display;
dp->convert_to_dp_mode(dp, bridge->dp_panel, mode, &dp_mode);
dp->clear_reservation(dp, bridge->dp_panel);
convert_to_drm_mode(&dp_mode, adjusted_mode);
end:
return ret;

View File

@@ -345,6 +345,7 @@ static bool dp_mst_bridge_mode_fixup(struct drm_bridge *drm_bridge,
dp = bridge->display;
dp->convert_to_dp_mode(dp, bridge_state->dp_panel, mode, &dp_mode);
dp->clear_reservation(dp, bridge_state->dp_panel);
convert_to_drm_mode(&dp_mode, adjusted_mode);
DP_MST_DEBUG("mst bridge [%d] mode:%s fixup\n", bridge->id, mode->name);
@@ -775,6 +776,7 @@ static void dp_mst_bridge_mode_set(struct drm_bridge *drm_bridge,
memcpy(&bridge->drm_mode, adjusted_mode, sizeof(bridge->drm_mode));
dp->convert_to_dp_mode(dp, bridge->dp_panel, adjusted_mode,
&bridge->dp_mode);
dp->clear_reservation(dp, dp_bridge_state->dp_panel);
DP_MST_INFO("mst bridge:%d conn:%d mode set complete %s\n", bridge->id,
DP_MST_CONN_ID(bridge), mode->name);

View File

@@ -137,6 +137,7 @@ struct dp_panel {
u32 pbn;
u32 dsc_blks_in_use;
u32 max_lm;
/* DRM connector assosiated with this panel */
struct drm_connector *connector;

View File

@@ -164,7 +164,9 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
enum dsi_test_pattern type,
u32 init_val,
u32 stream_id);
void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable);
void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable,
enum dsi_ctrl_tpg_pattern pattern,
enum dsi_op_mode panel_mode);
void dsi_ctrl_hw_cmn_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl,
u32 stream_id);

View File

@@ -3741,7 +3741,9 @@ error:
*
* Return: error code.
*/
int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on)
int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on,
enum dsi_test_pattern type, u32 init_val,
enum dsi_ctrl_tpg_pattern pattern)
{
int rc = 0;
@@ -3760,19 +3762,13 @@ int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on)
}
if (on) {
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) {
dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw,
DSI_TEST_PATTERN_INC,
0xFFFF);
} else {
dsi_ctrl->hw.ops.cmd_test_pattern_setup(
&dsi_ctrl->hw,
DSI_TEST_PATTERN_INC,
0xFFFF,
0x0);
}
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE)
dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw, type, init_val);
else
dsi_ctrl->hw.ops.cmd_test_pattern_setup(&dsi_ctrl->hw, type, init_val, 0x0);
}
dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on);
dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on, pattern,
dsi_ctrl->host_config.panel_mode);
DSI_CTRL_DEBUG(dsi_ctrl, "Set test pattern state=%d\n", on);
dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_TPG, on);
@@ -3781,6 +3777,30 @@ error:
return rc;
}
/**
* dsi_ctrl_trigger_test_pattern() - trigger a command mode frame update with test pattern
* @dsi_ctrl: DSI controller handle.
*
* Trigger a command mode frame update with chosen test pattern.
*
* Return: error code.
*/
int dsi_ctrl_trigger_test_pattern(struct dsi_ctrl *dsi_ctrl)
{
int ret = 0;
if (!dsi_ctrl) {
DSI_CTRL_ERR(dsi_ctrl, "Invalid params\n");
return -EINVAL;
}
mutex_lock(&dsi_ctrl->ctrl_lock);
dsi_ctrl->hw.ops.trigger_cmd_test_pattern(&dsi_ctrl->hw, 0);
mutex_unlock(&dsi_ctrl->ctrl_lock);
return ret;
}
/**
* dsi_ctrl_set_host_engine_state() - set host engine state
* @dsi_ctrl: DSI Controller handle.

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
@@ -573,13 +574,28 @@ int dsi_ctrl_set_roi(struct dsi_ctrl *dsi_ctrl, struct dsi_rect *roi,
* dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller
* @dsi_ctrl: DSI controller handle.
* @on: enable/disable test pattern.
* @type: type of test pattern to generate.
* @init_val: seed value for generating test pattern.
* @pattern: test pattern to generate.
*
* Test pattern can be enabled only after Video engine (for video mode panels)
* or command engine (for cmd mode panels) is enabled.
*
* Return: error code.
*/
int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on);
int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on,
enum dsi_test_pattern type, u32 init_val,
enum dsi_ctrl_tpg_pattern pattern);
/**
* dsi_ctrl_trigger_test_pattern() - trigger a command mode frame update with test pattern
* @dsi_ctrl: DSI controller handle.
*
* Trigger a command mode frame update with chosen test pattern.
*
* Return: error code.
*/
int dsi_ctrl_trigger_test_pattern(struct dsi_ctrl *dsi_ctrl);
/**
* dsi_ctrl_transfer_prepare() - Set up a command transfer

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
@@ -41,6 +42,29 @@
*/
#define DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER 0x1
/**
* enum dsi_ctrl_tpg_pattern - type of TPG pattern
* @DSI_CTRL_TPG_COUNTER:
* @DSI_CTRL_TPG_FIXED:
* @DSI_CTRL_TPG_COLOR_RAMP_64L_64P:
* @DSI_CTRL_TPG_COLOR_RAMP_64L_256P:
* @DSI_CTRL_TPG_GRAYSCALE_RAMP:
* @DSI_CTRL_TPG_COLOR_SQUARE:
* @DSI_CTRL_TPG_CHECKERED_RECTANGLE:
* @DSI_CTRL_TPG_BASIC_COLOR_CHANGING:
*/
enum dsi_ctrl_tpg_pattern {
DSI_CTRL_TPG_COUNTER = 0,
DSI_CTRL_TPG_FIXED,
DSI_CTRL_TPG_COLOR_RAMP_64L_64P,
DSI_CTRL_TPG_COLOR_RAMP_64L_256P,
DSI_CTRL_TPG_BLACK_WHITE_VERTICAL_LINES,
DSI_CTRL_TPG_GRAYSCALE_RAMP,
DSI_CTRL_TPG_COLOR_SQUARE,
DSI_CTRL_TPG_CHECKERED_RECTANGLE,
DSI_CTRL_TPG_BASIC_COLOR_CHANGING
};
/**
* enum dsi_ctrl_version - version of the dsi host controller
* @DSI_CTRL_VERSION_UNKNOWN: Unknown controller version
@@ -92,12 +116,14 @@ enum dsi_ctrl_hw_features {
* @DSI_TEST_PATTERN_FIXED: Test pattern is fixed, based on init value.
* @DSI_TEST_PATTERN_INC: Incremental test pattern, base on init value.
* @DSI_TEST_PATTERN_POLY: Pattern generated from polynomial and init val.
* @DSI_TEST_PATTERN_GENERAL: MDSS general test pattern.
* @DSI_TEST_PATTERN_MAX:
*/
enum dsi_test_pattern {
DSI_TEST_PATTERN_FIXED = 0,
DSI_TEST_PATTERN_INC,
DSI_TEST_PATTERN_POLY,
DSI_TEST_PATTERN_GENERAL,
DSI_TEST_PATTERN_MAX
};
@@ -727,8 +753,12 @@ struct dsi_ctrl_hw_ops {
* test_pattern_enable() - enable test pattern engine
* @ctrl: Pointer to the controller host hardware.
* @enable: Enable/Disable test pattern engine.
* @pattern: Type of TPG pattern
* @panel_mode: DSI operation mode
*/
void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable);
void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable,
enum dsi_ctrl_tpg_pattern pattern,
enum dsi_op_mode panel_mode);
/**
* clear_phy0_ln_err() - clear DSI PHY lane-0 errors

View File

@@ -1516,20 +1516,23 @@ void dsi_ctrl_hw_cmn_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
enum dsi_test_pattern type,
u32 init_val)
{
u32 reg = 0;
u32 reg = 0, pattern_sel_shift = 4;
DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL, init_val);
switch (type) {
case DSI_TEST_PATTERN_FIXED:
reg |= (0x2 << 4);
reg |= (0x2 << pattern_sel_shift);
break;
case DSI_TEST_PATTERN_INC:
reg |= (0x1 << 4);
reg |= (0x1 << pattern_sel_shift);
break;
case DSI_TEST_PATTERN_POLY:
DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_POLY, 0xF0F0F);
break;
case DSI_TEST_PATTERN_GENERAL:
reg |= (0x3 << pattern_sel_shift);
break;
default:
break;
}
@@ -1590,6 +1593,9 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
case DSI_TEST_PATTERN_POLY:
DSI_W32(ctrl, poly_offset, 0xF0F0F);
break;
case DSI_TEST_PATTERN_GENERAL:
reg |= (0x3 << pattern_sel_shift);
break;
default:
break;
}
@@ -1602,11 +1608,28 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
* test_pattern_enable() - enable test pattern engine
* @ctrl: Pointer to the controller host hardware.
* @enable: Enable/Disable test pattern engine.
* @pattern: Type of TPG pattern
* @panel_mode: DSI operation mode
*/
void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl,
bool enable)
bool enable, enum dsi_ctrl_tpg_pattern pattern,
enum dsi_op_mode panel_mode)
{
u32 reg = DSI_R32(ctrl, DSI_TEST_PATTERN_GEN_CTRL);
u32 reg_tpg_main_control = 0;
u32 reg_tpg_video_config = BIT(0);
reg_tpg_video_config |= BIT(2);
if (panel_mode == DSI_OP_CMD_MODE) {
reg_tpg_main_control = BIT(pattern);
DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL2, reg_tpg_main_control);
} else {
reg_tpg_main_control = BIT(pattern + 1);
DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL, reg_tpg_main_control);
}
DSI_W32(ctrl, DSI_TPG_VIDEO_CONFIG, reg_tpg_video_config);
if (enable)
reg |= BIT(0);

View File

@@ -7763,7 +7763,10 @@ error:
return rc;
}
int dsi_display_set_tpg_state(struct dsi_display *display, bool enable)
int dsi_display_set_tpg_state(struct dsi_display *display, bool enable,
enum dsi_test_pattern type,
u32 init_val,
enum dsi_ctrl_tpg_pattern pattern)
{
int rc = 0;
int i;
@@ -7776,12 +7779,18 @@ int dsi_display_set_tpg_state(struct dsi_display *display, bool enable)
display_for_each_ctrl(i, display) {
ctrl = &display->ctrl[i];
rc = dsi_ctrl_set_tpg_state(ctrl->ctrl, enable);
rc = dsi_ctrl_set_tpg_state(ctrl->ctrl, enable, type, init_val, pattern);
if (rc) {
DSI_ERR("[%s] failed to set tpg state for host_%d\n",
display->name, i);
DSI_ERR("[%s] failed to set tpg state for host_%d\n", display->name, i);
goto error;
}
if (enable && ctrl->ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
rc = dsi_ctrl_trigger_test_pattern(ctrl->ctrl);
if (rc) {
DSI_ERR("[%s] failed to start tpg for host_%d\n", display->name, i);
goto error;
}
}
}
display->is_tpg_enabled = enable;

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
@@ -633,7 +634,10 @@ int dsi_pre_clkon_cb(void *priv, enum dsi_clk_type clk_type,
*/
int dsi_display_unprepare(struct dsi_display *display);
int dsi_display_set_tpg_state(struct dsi_display *display, bool enable);
int dsi_display_set_tpg_state(struct dsi_display *display, bool enable,
enum dsi_test_pattern type,
u32 init_val,
enum dsi_ctrl_tpg_pattern pattern);
int dsi_display_clock_gate(struct dsi_display *display, bool enable);
int dsi_dispaly_static_frame(struct dsi_display *display, bool enable);

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/kernel.h>
@@ -1556,7 +1557,8 @@ int dsi_pll_5nm_configure(void *pll, bool commit)
if (rsc->slave)
dsi_pll_enable_pll_bias(rsc->slave);
dsi_pll_init_val(rsc);
if (commit)
dsi_pll_init_val(rsc);
rc = dsi_pll_5nm_set_byteclk_div(rsc, commit);

View File

@@ -828,6 +828,7 @@ struct msm_mode_info {
/**
* struct msm_resource_caps_info - defines hw resources
* @num_lm_in_use number of layer mixers allocated to a specified encoder
* @num_lm number of layer mixers available
* @num_dsc number of dsc available
* @num_vdc number of vdc available
@@ -836,6 +837,7 @@ struct msm_mode_info {
* @max_mixer_width: max width supported by layer mixer
*/
struct msm_resource_caps_info {
uint32_t num_lm_in_use;
uint32_t num_lm;
uint32_t num_dsc;
uint32_t num_vdc;

View File

@@ -1617,6 +1617,8 @@ static int _sde_cp_crtc_checkfeature(u32 feature,
hw_cfg.num_of_mixers = sde_crtc->num_mixers;
hw_cfg.last_feature = 0;
hw_cfg.panel_width = sde_crtc_state->base.adjusted_mode.hdisplay;
hw_cfg.panel_height = sde_crtc_state->base.adjusted_mode.vdisplay;
for (i = 0; i < num_mixers; i++) {
hw_dspp = sde_crtc->mixers[i].hw_dspp;
@@ -1625,6 +1627,7 @@ static int _sde_cp_crtc_checkfeature(u32 feature,
hw_cfg.dspp[i] = hw_dspp;
}
SDE_EVT32(feature, hw_cfg.panel_width, hw_cfg.panel_height);
for (i = 0; i < num_mixers && !ret; i++) {
hw_lm = sde_crtc->mixers[i].hw_lm;
hw_dspp = sde_crtc->mixers[i].hw_dspp;
@@ -1639,8 +1642,6 @@ static int _sde_cp_crtc_checkfeature(u32 feature,
hw_cfg.displayh = num_mixers *
sde_crtc_state->lm_roi[i].w;
hw_cfg.displayv = sde_crtc_state->lm_roi[i].h;
hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay;
hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay;
DRM_DEBUG_DRIVER("check cp feature %d on mixer %d\n",
feature, hw_lm->idx - LM_0);
ret = check_feature(hw_dspp, &hw_cfg, sde_crtc);
@@ -1685,7 +1686,7 @@ static void _sde_cp_crtc_commit_feature(struct sde_cp_node *prop_node,
hw_cfg.num_ds_enabled = sde_crtc_state->num_ds_enabled;
SDE_EVT32(hw_cfg.panel_width, hw_cfg.panel_height);
SDE_EVT32(prop_node->feature, hw_cfg.panel_width, hw_cfg.panel_height);
for (i = 0; i < num_mixers; i++) {
hw_dspp = sde_crtc->mixers[i].hw_dspp;
@@ -1888,6 +1889,9 @@ static int _sde_cp_crtc_check_pu_features(struct drm_crtc *crtc)
hw_cfg.num_of_mixers = sde_crtc->num_mixers;
hw_cfg.payload = &sde_crtc_state->user_roi_list;
hw_cfg.len = sizeof(sde_crtc_state->user_roi_list);
hw_cfg.panel_height = sde_crtc_state->base.adjusted_mode.vdisplay;
hw_cfg.panel_width = sde_crtc_state->base.adjusted_mode.hdisplay;
for (i = 0; i < hw_cfg.num_of_mixers; i++)
hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp;
@@ -1899,6 +1903,7 @@ static int _sde_cp_crtc_check_pu_features(struct drm_crtc *crtc)
!(sde_crtc->cp_pu_feature_mask & BIT(i)))
continue;
SDE_EVT32(i, hw_cfg.panel_width, hw_cfg.panel_height);
for (j = 0; j < hw_cfg.num_of_mixers; j++) {
hw_dspp = sde_crtc->mixers[j].hw_dspp;
@@ -1908,8 +1913,7 @@ static int _sde_cp_crtc_check_pu_features(struct drm_crtc *crtc)
hw_cfg.displayh = hw_cfg.num_of_mixers *
sde_crtc_state->lm_roi[j].w;
hw_cfg.displayv = sde_crtc_state->lm_roi[j].h;
hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay;
hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay;
ret = check_pu_feature(hw_dspp, &hw_cfg, sde_crtc);
if (ret) {
DRM_ERROR("failed pu feature %d in mixer %d\n",
@@ -2062,6 +2066,7 @@ static int _sde_cp_crtc_update_pu_features(struct drm_crtc *crtc, bool *need_flu
!(sde_crtc->cp_pu_feature_mask & BIT(i)))
continue;
SDE_EVT32(i, hw_cfg.panel_width, hw_cfg.panel_height);
for (j = 0; j < hw_cfg.num_of_mixers; j++) {
hw_lm = sde_crtc->mixers[j].hw_lm;
hw_dspp = sde_crtc->mixers[j].hw_dspp;
@@ -2071,8 +2076,6 @@ static int _sde_cp_crtc_update_pu_features(struct drm_crtc *crtc, bool *need_flu
hw_cfg.displayh = hw_cfg.num_of_mixers *
hw_lm->cfg.out_width;
hw_cfg.displayv = hw_lm->cfg.out_height;
hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay;
hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay;
ret = set_pu_feature(hw_dspp, &hw_cfg, sde_crtc);
/* feature does not need flush when ret > 0 */

View File

@@ -1360,15 +1360,17 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc,
{
struct sde_crtc *sde_crtc;
struct sde_crtc_state *sde_crtc_state;
struct msm_mode_info mode_info;
struct msm_mode_info *mode_info;
u32 crtc_width, crtc_height, mixer_width, mixer_height;
struct drm_display_mode *adj_mode;
int rc, lm_idx, i;
int rc = 0, lm_idx, i;
if (!crtc || !state)
return -EINVAL;
memset(&mode_info, 0, sizeof(mode_info));
mode_info = kzalloc(sizeof(struct msm_mode_info), GFP_KERNEL);
if (!mode_info)
return -ENOMEM;
sde_crtc = to_sde_crtc(crtc);
sde_crtc_state = to_sde_crtc_state(state);
@@ -1383,7 +1385,8 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc,
SDE_ERROR("%s: invalid w/h crtc:%d,%d, mixer:%d,%d, num_mixers:%d\n",
sde_crtc->name, crtc_width, crtc_height, mixer_width, mixer_height,
sde_crtc->num_mixers);
return -EINVAL;
rc = -EINVAL;
goto end;
}
/*
@@ -1396,54 +1399,58 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc,
if (!conn || !conn->state)
continue;
rc = sde_connector_state_get_mode_info(conn->state, &mode_info);
rc = sde_connector_state_get_mode_info(conn->state, mode_info);
if (rc) {
SDE_ERROR("failed to get mode info\n");
return -EINVAL;
rc = -EINVAL;
goto end;
}
if (sde_connector_is_3d_merge_enabled(conn) && (mixer_width % 2)) {
SDE_ERROR(
"%s: invalid width w/ 3d-merge - mixer_w:%d, crtc_w:%d, num_mixers:%d\n",
sde_crtc->name, crtc_width, mixer_width, sde_crtc->num_mixers);
return -EINVAL;
rc = -EINVAL;
goto end;
}
if (!mode_info.roi_caps.enabled)
if (!mode_info->roi_caps.enabled)
continue;
if (sde_crtc_state->user_roi_list.num_rects >
mode_info.roi_caps.num_roi) {
mode_info->roi_caps.num_roi) {
SDE_ERROR("roi count is exceeding limit, %d > %d\n",
sde_crtc_state->user_roi_list.num_rects,
mode_info.roi_caps.num_roi);
return -E2BIG;
mode_info->roi_caps.num_roi);
rc = -E2BIG;
goto end;
}
rc = _sde_crtc_set_crtc_roi(crtc, state);
if (rc)
return rc;
goto end;
rc = _sde_crtc_check_autorefresh(crtc, state);
if (rc)
return rc;
goto end;
for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
rc = _sde_crtc_set_lm_roi(crtc, state, lm_idx);
if (rc)
return rc;
goto end;
}
rc = _sde_crtc_check_rois_centered_and_symmetric(crtc, state);
if (rc)
return rc;
goto end;
rc = _sde_crtc_check_planes_within_crtc_roi(crtc, state);
if (rc)
return rc;
goto end;
}
return 0;
end:
kfree(mode_info);
return rc;
}
static u32 _sde_crtc_calc_gcd(u32 a, u32 b)

View File

@@ -3272,6 +3272,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
phys->ops.disable(phys);
}
} else {
sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

View File

@@ -549,6 +549,7 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc, bo
{
struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
struct sde_hw_wb *hw_wb = wb_enc->hw_wb;
struct sde_hw_wb_cfg *wb_cfg = &wb_enc->wb_cfg;
struct sde_hw_ctl *hw_ctl = phys_enc->hw_ctl;
struct sde_crtc *crtc = to_sde_crtc(wb_enc->crtc);
struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp;
@@ -606,6 +607,9 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc, bo
test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features))
hw_wb->ops.bind_dcwb_pp_blk(hw_wb, enable, hw_pp->idx);
if (hw_wb->ops.setup_crop && !enable)
hw_wb->ops.setup_crop(hw_wb, wb_cfg, false);
if (hw_ctl->ops.update_intf_cfg) {
hw_ctl->ops.update_intf_cfg(hw_ctl, &intf_cfg, enable);
SDE_DEBUG("[enc:%d wb:%d] in CWB/DCWB mode on CTL_%d PP-%d merge3d:%d\n",

View File

@@ -749,6 +749,7 @@ int sde_hw_rc_check_mask(struct sde_hw_dspp *hw_dspp, void *cfg)
if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) {
SDE_DEBUG("RC feature disabled, skip mask checks\n");
SDE_EVT32(RC_IDX(hw_dspp));
return 0;
}
@@ -802,6 +803,7 @@ int sde_hw_rc_check_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg)
SDE_DEBUG("full frame update\n");
memset(&empty_roi_list, 0, sizeof(struct msm_roi_list));
roi_list = &empty_roi_list;
SDE_EVT32(RC_IDX(hw_dspp));
}
rc_mask_cfg = RC_STATE(hw_dspp).last_rc_mask_cfg;
@@ -810,6 +812,7 @@ int sde_hw_rc_check_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg)
/* early return when there is no mask in memory */
if (!mask_programmed || !rc_mask_cfg) {
SDE_DEBUG("no previous rc mask programmed\n");
SDE_EVT32(RC_IDX(hw_dspp));
return SDE_HW_RC_PU_SKIP_OP;
}
@@ -869,10 +872,12 @@ int sde_hw_rc_setup_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg)
rc_mask_cfg = RC_STATE(hw_dspp).last_rc_mask_cfg;
mask_programmed = RC_STATE(hw_dspp).mask_programmed;
SDE_EVT32(RC_IDX(hw_dspp), roi_list, rc_mask_cfg, mask_programmed);
/* early return when there is no mask in memory */
if (!mask_programmed || !rc_mask_cfg) {
SDE_DEBUG("no previous rc mask programmed\n");
SDE_EVT32(RC_IDX(hw_dspp));
return SDE_HW_RC_PU_SKIP_OP;
}
@@ -936,7 +941,9 @@ int sde_hw_rc_setup_mask(struct sde_hw_dspp *hw_dspp, void *cfg)
memset(RC_STATE(hw_dspp).last_roi_list, 0,
sizeof(struct msm_roi_list));
RC_STATE(hw_dspp).roi_programmed = false;
SDE_EVT32(RC_IDX(hw_dspp), RC_STATE(hw_dspp).last_rc_mask_cfg,
RC_STATE(hw_dspp).mask_programmed,
RC_STATE(hw_dspp).roi_programmed);
return 0;
}
@@ -957,6 +964,7 @@ int sde_hw_rc_setup_mask(struct sde_hw_dspp *hw_dspp, void *cfg)
SDE_DEBUG("partial frame update\n");
sde_kms_rect_merge_rectangles(last_roi_list, &merged_roi);
}
SDE_EVT32(RC_IDX(hw_dspp), roi_programmed);
rc = _sde_hw_rc_get_ajusted_roi(hw_cfg, &merged_roi, &rc_roi);
if (rc) {
@@ -1003,6 +1011,7 @@ int sde_hw_rc_setup_data_dma(struct sde_hw_dspp *hw_dspp, void *cfg)
if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) {
SDE_DEBUG("RC feature disabled, skip data programming\n");
SDE_EVT32(RC_IDX(hw_dspp));
return 0;
}
@@ -1016,6 +1025,7 @@ int sde_hw_rc_setup_data_dma(struct sde_hw_dspp *hw_dspp, void *cfg)
if (rc_mask_cfg->flags & SDE_HW_RC_SKIP_DATA_PROG) {
SDE_DEBUG("skip data programming\n");
SDE_EVT32(RC_IDX(hw_dspp));
return 0;
}
@@ -1042,6 +1052,7 @@ int sde_hw_rc_setup_data_ahb(struct sde_hw_dspp *hw_dspp, void *cfg)
if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) {
SDE_DEBUG("rc feature disabled, skip data programming\n");
SDE_EVT32(RC_IDX(hw_dspp));
return 0;
}
@@ -1055,6 +1066,7 @@ int sde_hw_rc_setup_data_ahb(struct sde_hw_dspp *hw_dspp, void *cfg)
if (rc_mask_cfg->flags & SDE_HW_RC_SKIP_DATA_PROG) {
SDE_DEBUG("skip data programming\n");
SDE_EVT32(RC_IDX(hw_dspp));
return 0;
}

View File

@@ -445,9 +445,10 @@ void sde_hw_setup_scaler3(struct sde_hw_blk_reg_map *c,
de_lpf_blend = (scaler3_cfg->de_lpf_l & 0x3FF) |
((scaler3_cfg->de_lpf_m & 0x3FF) << 10) |
((scaler3_cfg->de_lpf_h & 0x3FF) << 20);
SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND, de_lpf_blend);
SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND +
scaler_offset, de_lpf_blend);
} else {
SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND,
SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND + scaler_offset,
QSEED5_DEFAULT_DE_LPF_BLEND);
}
}

View File

@@ -286,27 +286,33 @@ void sde_rm_get_resource_info(struct sde_rm *rm,
{
struct sde_rm_hw_blk *blk;
enum sde_hw_blk_type type;
struct sde_rm_rsvp rsvp;
const struct sde_lm_cfg *lm_cfg;
bool is_built_in, is_pref;
u32 lm_pref = (BIT(SDE_DISP_PRIMARY_PREF) | BIT(SDE_DISP_SECONDARY_PREF));
mutex_lock(&rm->rm_lock);
/* Get all currently available resources */
memcpy(avail_res, &rm->avail_res,
sizeof(rm->avail_res));
/**
* When the encoder is null, assume display is external in order to return the count of
* availalbe non-preferred LMs
*/
if (!drm_enc)
return;
is_built_in = sde_encoder_is_built_in_display(drm_enc);
rsvp.enc_id = drm_enc->base.id;
is_built_in = false;
else
is_built_in = sde_encoder_is_built_in_display(drm_enc);
for (type = 0; type < SDE_HW_BLK_MAX; type++) {
list_for_each_entry(blk, &rm->hw_blks[type], list) {
/* Add back resources allocated to the given encoder */
if (blk->rsvp && blk->rsvp->enc_id == rsvp.enc_id)
if (blk->rsvp && drm_enc && blk->rsvp->enc_id == drm_enc->base.id) {
_sde_rm_inc_resource_info(rm, avail_res, blk);
if (type == SDE_HW_BLK_LM)
avail_res->num_lm_in_use++;
}
/**
* Remove unallocated preferred lms that cannot reserved
@@ -316,11 +322,13 @@ void sde_rm_get_resource_info(struct sde_rm *rm,
lm_cfg = to_sde_hw_mixer(blk->hw)->cap;
is_pref = lm_cfg->features & lm_pref;
if (!blk->rsvp && !is_built_in && is_pref)
if (!blk->rsvp && !blk->rsvp_nxt && !is_built_in && is_pref)
_sde_rm_dec_resource_info(rm, avail_res, blk);
}
}
}
mutex_unlock(&rm->rm_lock);
}
static void _sde_rm_print_rsvps(