Merge "disp: msm: dp: ensure failsafe mode in connector mode list"

This commit is contained in:
qctecmdr
2023-06-08 13:43:43 -07:00
committed by Gerrit - the friendly Code Review server
5 changed files with 86 additions and 45 deletions

View File

@@ -3040,6 +3040,12 @@ static enum drm_mode_status dp_display_validate_mode(
dp_display->convert_to_dp_mode(dp_display, panel, mode, &dp_mode);
/* As per spec, 640x480 mode should always be present as fail-safe */
if ((dp_mode.timing.h_active == 640) && (dp_mode.timing.v_active == 480) &&
(dp_mode.timing.pixel_clk_khz == 25175)) {
goto skip_validation;
}
rc = dp_display_validate_topology(dp, dp_panel, mode, &dp_mode, avail_res);
if (rc == -EAGAIN) {
dp_panel->convert_to_dp_mode(dp_panel, mode, &dp_mode);
@@ -3057,6 +3063,7 @@ static enum drm_mode_status dp_display_validate_mode(
if (rc)
goto end;
skip_validation:
mode_status = MODE_OK;
if (!avail_res->num_lm_in_use) {
@@ -3070,7 +3077,7 @@ static enum drm_mode_status dp_display_validate_mode(
end:
mutex_unlock(&dp->session_lock);
DP_DEBUG_V("[%s] mode is %s\n", mode->name,
DP_DEBUG_V("[%s clk:%d] mode is %s\n", mode->name, mode->clock,
(mode_status == MODE_OK) ? "valid" : "invalid");
return mode_status;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
@@ -308,6 +308,47 @@ static const struct drm_bridge_funcs dp_bridge_ops = {
.mode_set = dp_bridge_mode_set,
};
int dp_connector_add_custom_mode(struct drm_connector *conn, struct dp_display_mode *dp_mode)
{
struct drm_display_mode *m, drm_mode;
memset(&drm_mode, 0x0, sizeof(drm_mode));
convert_to_drm_mode(dp_mode, &drm_mode);
m = drm_mode_duplicate(conn->dev, &drm_mode);
if (!m) {
DP_ERR("failed to add mode %ux%u\n", drm_mode.hdisplay, drm_mode.vdisplay);
return 0;
}
m->width_mm = conn->display_info.width_mm;
m->height_mm = conn->display_info.height_mm;
drm_mode_probed_add(conn, m);
return 1;
}
void init_failsafe_mode(struct dp_display_mode *dp_mode)
{
static const struct dp_panel_info fail_safe = {
.h_active = 640,
.v_active = 480,
.h_back_porch = 48,
.h_front_porch = 16,
.h_sync_width = 96,
.h_active_low = 1,
.v_back_porch = 33,
.v_front_porch = 10,
.v_sync_width = 2,
.v_active_low = 1,
.h_skew = 0,
.refresh_rate = 60,
.pixel_clk_khz = 25175,
.bpp = 24,
.widebus_en = true,
};
memcpy(&dp_mode->timing, &fail_safe, sizeof(fail_safe));
}
int dp_connector_config_hdr(struct drm_connector *connector, void *display,
struct sde_connector_state *c_state)
{
@@ -558,7 +599,6 @@ int dp_connector_get_modes(struct drm_connector *connector,
int rc = 0;
struct dp_display *dp;
struct dp_display_mode *dp_mode = NULL;
struct drm_display_mode *m, drm_mode;
struct sde_connector *sde_conn;
if (!connector || !display)
@@ -578,25 +618,19 @@ int dp_connector_get_modes(struct drm_connector *connector,
/* pluggable case assumes EDID is read when HPD */
if (dp->is_sst_connected) {
/*
* 1. for test request, rc = 1, and dp_mode will have test mode populated
* 2. During normal operation, dp_mode will be untouched
* a. if mode query succeeds rc >= 0, valid modes will be added to connector
* b. if edid read failed, then connector mode list will be empty and rc <= 0
*/
rc = dp->get_modes(dp, sde_conn->drv_panel, dp_mode);
if (!rc)
DP_ERR("failed to get DP sink modes, rc=%d\n", rc);
if (dp_mode->timing.pixel_clk_khz) { /* valid DP mode */
memset(&drm_mode, 0x0, sizeof(drm_mode));
convert_to_drm_mode(dp_mode, &drm_mode);
m = drm_mode_duplicate(connector->dev, &drm_mode);
if (!m) {
DP_ERR("failed to add mode %ux%u\n",
drm_mode.hdisplay,
drm_mode.vdisplay);
kfree(dp_mode);
return 0;
}
m->width_mm = connector->display_info.width_mm;
m->height_mm = connector->display_info.height_mm;
drm_mode_probed_add(connector, m);
if (!rc) {
DP_WARN("failed to get DP sink modes, adding failsafe");
init_failsafe_mode(dp_mode);
}
if (dp_mode->timing.pixel_clk_khz) /* valid DP mode */
rc = dp_connector_add_custom_mode(connector, dp_mode);
} else {
DP_ERR("No sink connected\n");
}

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
@@ -168,6 +169,19 @@ int dp_connector_update_pps(struct drm_connector *connector,
int dp_connector_install_properties(void *display,
struct drm_connector *conn);
/**
* init_failsafe_mode - add failsafe edid mode
* @dp_mode: Pointer to mode
*/
void init_failsafe_mode(struct dp_display_mode *dp_mode);
/**
* dp_connector_add_custom_mode - add edid mode to connector
* @conn: Pointer to connector
* @dp_mode: Pointer to mode
*/
int dp_connector_add_custom_mode(struct drm_connector *conn, struct dp_display_mode *dp_mode);
#else
static inline int dp_connector_config_hdr(struct drm_connector *connector,
void *display, struct sde_connector_state *c_state)

View File

@@ -1178,6 +1178,7 @@ static int dp_mst_connector_get_modes(struct drm_connector *connector,
struct sde_connector *c_conn = to_sde_connector(connector);
struct dp_display *dp_display = display;
struct dp_mst_private *mst = dp_display->dp_mst_prv_info;
struct dp_display_mode *dp_mode = NULL;
int rc = 0;
struct edid *edid = NULL;
@@ -1195,7 +1196,7 @@ static int dp_mst_connector_get_modes(struct drm_connector *connector,
&mst->mst_mgr, c_conn->mst_port);
if (!edid) {
DP_ERR("get edid failed. id: %d\n", connector->base.id);
DP_WARN("get edid failed. id: %d\n", connector->base.id);
goto end;
}
@@ -1220,8 +1221,13 @@ duplicate_edid:
end:
SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, connector->base.id, rc);
if (rc <= 0) {
DP_ERR("conn:%d has no modes, rc=%d\n", connector->base.id, rc);
rc = 0;
DP_WARN("conn:%d has no modes, adding failsafe. rc=%d\n", connector->base.id, rc);
dp_mode = kzalloc(sizeof(*dp_mode), GFP_KERNEL);
if (!dp_mode)
return 0;
init_failsafe_mode(dp_mode);
rc = dp_connector_add_custom_mode(connector, dp_mode);
} else {
DP_MST_INFO("conn:%d has %d modes\n", connector->base.id, rc);
}

View File

@@ -84,23 +84,6 @@ struct dp_panel_private {
u8 minor;
};
static const struct dp_panel_info fail_safe = {
.h_active = 640,
.v_active = 480,
.h_back_porch = 48,
.h_front_porch = 16,
.h_sync_width = 96,
.h_active_low = 0,
.v_back_porch = 33,
.v_front_porch = 10,
.v_sync_width = 2,
.v_active_low = 0,
.h_skew = 0,
.refresh_rate = 60,
.pixel_clk_khz = 25200,
.bpp = 24,
};
/* OEM NAME */
static const u8 vendor_name[8] = {81, 117, 97, 108, 99, 111, 109, 109};
@@ -1540,7 +1523,7 @@ static int dp_panel_dsc_prepare_basic_params(
* 2. The ppr per slice cannot exceed the maximum.
* 3. The number of slices must be explicitly supported.
*/
while (slice_width >= max_slice_width ||
while (slice_width > max_slice_width ||
ppr_per_slice > peak_throughput ||
!dp_panel_check_slice_support(
comp_info->dsc_info.slice_per_pkt, slice_caps_1,
@@ -2060,10 +2043,7 @@ static int dp_panel_get_modes(struct dp_panel *dp_panel,
return _sde_edid_update_modes(connector, dp_panel->edid_ctrl);
}
/* fail-safe mode */
memcpy(&mode->timing, &fail_safe,
sizeof(fail_safe));
return 1;
return 0;
}
static void dp_panel_handle_sink_request(struct dp_panel *dp_panel)