Merge "disp: msm: sde: add multi-mode RFI support"

Цей коміт міститься в:
qctecmdr
2021-03-24 14:16:57 -07:00
зафіксовано Gerrit - the friendly Code Review server
джерело b884dbf3e7 c5f2bd7401
коміт 7d1ca7c295
14 змінених файлів з 335 додано та 74 видалено

Переглянути файл

@@ -587,6 +587,16 @@ struct dsi_host_config {
struct dsi_lane_map lane_map;
};
/**
* struct dyn_clk_list - list of dynamic clock rates.
* @rates: list of supported clock rates
* @count: number of supported clock rates
*/
struct dyn_clk_list {
u32 *rates;
u32 count;
};
/**
* struct dsi_display_mode_priv_info - private mode info that will be attached
* with each drm mode
@@ -600,6 +610,7 @@ struct dsi_host_config {
* @dsi_transfer_time_us: Specifies the dsi transfer time for cmd panels.
* @clk_rate_hz: DSI bit clock per lane in hz.
* @min_dsi_clk_hz: Min dsi clk per lane to transfer frame in vsync time.
* @bit_clk_list: List of dynamic bit clock rates supported.
* @topology: Topology selected for the panel
* @dsc: DSC compression info
* @vdc: VDC compression info
@@ -623,6 +634,7 @@ struct dsi_display_mode_priv_info {
u32 dsi_transfer_time_us;
u64 clk_rate_hz;
u64 min_dsi_clk_hz;
struct dyn_clk_list bit_clk_list;
struct msm_display_topology topology;
struct msm_display_dsc_info dsc;

Переглянути файл

@@ -6678,12 +6678,11 @@ static void _dsi_display_populate_bit_clks(struct dsi_display *display,
src = &display->modes[i];
if (!src)
return;
/*
* TODO: currently setting the first bit rate in
* the list as preferred rate. But ideally should
* be based on user or device tree preferrence.
*/
src->timing.clk_rate_hz = dyn_clk_caps->bit_clk_list[0];
if (!src->priv_info->bit_clk_list.count)
continue;
src->timing.clk_rate_hz = src->priv_info->bit_clk_list.rates[0];
dsi_display_adjust_mode_timing(display, src, lanes, bpp);
@@ -6726,6 +6725,37 @@ static void _dsi_display_populate_bit_clks(struct dsi_display *display,
}
}
int dsi_display_restore_bit_clk(struct dsi_display *display, struct dsi_display_mode *mode)
{
int i;
u32 clk_rate_hz = 0;
if (!display || !mode || !mode->priv_info) {
DSI_ERR("invalid arguments\n");
return -EINVAL;
}
clk_rate_hz = display->cached_clk_rate;
if (mode->priv_info->bit_clk_list.count) {
/* use first entry as the default bit clk rate */
clk_rate_hz = mode->priv_info->bit_clk_list.rates[0];
for (i = 0; i < mode->priv_info->bit_clk_list.count; i++) {
if (display->dyn_bit_clk == mode->priv_info->bit_clk_list.rates[i])
clk_rate_hz = display->dyn_bit_clk;
}
}
mode->timing.clk_rate_hz = clk_rate_hz;
mode->priv_info->clk_rate_hz = clk_rate_hz;
SDE_EVT32(clk_rate_hz, display->cached_clk_rate, display->dyn_bit_clk);
DSI_DEBUG("clk_rate_hz:%u, cached_clk_rate:%u, dyn_bit_clk:%u\n",
clk_rate_hz, display->cached_clk_rate, display->dyn_bit_clk);
return 0;
}
void dsi_display_put_mode(struct dsi_display *display,
struct dsi_display_mode *mode)
{
@@ -7237,9 +7267,11 @@ int dsi_display_set_mode(struct dsi_display *display,
}
}
/*For dynamic DSI setting, use specified clock rate */
if (display->cached_clk_rate > 0)
adj_mode.priv_info->clk_rate_hz = display->cached_clk_rate;
rc = dsi_display_restore_bit_clk(display, &adj_mode);
if (rc) {
DSI_ERR("[%s] bit clk rate cannot be restored\n", display->name);
goto error;
}
rc = dsi_display_validate_mode_set(display, &adj_mode, flags);
if (rc) {
@@ -7253,11 +7285,13 @@ int dsi_display_set_mode(struct dsi_display *display,
goto error;
}
DSI_INFO("mdp_transfer_time=%d, hactive=%d, vactive=%d, fps=%d\n",
DSI_INFO("mdp_transfer_time=%d, hactive=%d, vactive=%d, fps=%d, clk_rate=%llu\n",
adj_mode.priv_info->mdp_transfer_time_us,
timing.h_active, timing.v_active, timing.refresh_rate);
timing.h_active, timing.v_active, timing.refresh_rate,
adj_mode.priv_info->clk_rate_hz);
SDE_EVT32(adj_mode.priv_info->mdp_transfer_time_us,
timing.h_active, timing.v_active, timing.refresh_rate);
timing.h_active, timing.v_active, timing.refresh_rate,
adj_mode.priv_info->clk_rate_hz);
memcpy(display->panel->cur_mode, &adj_mode, sizeof(adj_mode));
error:
@@ -8366,6 +8400,67 @@ int dsi_display_update_pps(char *pps_cmd, void *disp)
return 0;
}
int dsi_display_update_dyn_bit_clk(struct dsi_display *display,
struct dsi_display_mode *mode)
{
struct dsi_dyn_clk_caps *dyn_clk_caps;
struct dsi_host_common_cfg *host_cfg;
int bpp, lanes = 0;
if (!display || !mode) {
DSI_ERR("invalid arguments\n");
return -EINVAL;
}
dyn_clk_caps = &(display->panel->dyn_clk_caps);
if (!dyn_clk_caps->dyn_clk_support) {
DSI_DEBUG("dynamic bit clock support not enabled\n");
return 0;
} else if (!display->dyn_bit_clk_pending) {
DSI_DEBUG("dynamic bit clock rate not updated\n");
return 0;
} else if (!display->dyn_bit_clk) {
DSI_DEBUG("dynamic bit clock rate cleared\n");
return 0;
} else if (display->dyn_bit_clk < mode->priv_info->min_dsi_clk_hz) {
DSI_ERR("dynamic bit clock rate %llu smaller than minimum value:%llu\n",
display->dyn_bit_clk, mode->priv_info->min_dsi_clk_hz);
return -EINVAL;
}
/* update mode clk rate with user value */
mode->timing.clk_rate_hz = display->dyn_bit_clk;
mode->priv_info->clk_rate_hz = display->dyn_bit_clk;
host_cfg = &(display->panel->host_config);
bpp = dsi_pixel_format_to_bpp(host_cfg->dst_format);
if (host_cfg->data_lanes & DSI_DATA_LANE_0)
lanes++;
if (host_cfg->data_lanes & DSI_DATA_LANE_1)
lanes++;
if (host_cfg->data_lanes & DSI_DATA_LANE_2)
lanes++;
if (host_cfg->data_lanes & DSI_DATA_LANE_3)
lanes++;
dsi_display_adjust_mode_timing(display, mode, lanes, bpp);
/* adjust pixel clock based on dynamic bit clock */
mode->pixel_clk_khz = div_u64(mode->timing.clk_rate_hz * lanes, bpp);
do_div(mode->pixel_clk_khz, 1000);
mode->pixel_clk_khz *= display->ctrl_count;
SDE_EVT32(display->dyn_bit_clk, mode->priv_info->min_dsi_clk_hz, mode->pixel_clk_khz);
DSI_DEBUG("dynamic bit clk:%u, min dsi clk:%llu, lanes:%d, bpp:%d, pck:%d Khz\n",
display->dyn_bit_clk, mode->priv_info->min_dsi_clk_hz, lanes, bpp,
mode->pixel_clk_khz);
display->dyn_bit_clk_pending = false;
return 0;
}
int dsi_display_dump_clks_state(struct dsi_display *display)
{
int rc = 0;

Переглянути файл

@@ -154,6 +154,8 @@ struct dsi_display_ext_bridge {
* index into the ctrl[MAX_DSI_CTRLS_PER_DISPLAY] array.
* @cmd_master_idx: The master controller for sending DSI commands to panel.
* @video_master_idx: The master controller for enabling video engine.
* @dyn_bit_clk: The DSI bit clock rate dynamically set by user mode client.
* @dyn_bit_clk_pending: Flag indicating the pending DSI dynamic bit clock rate change.
* @cached_clk_rate: The cached DSI clock rate set dynamically by sysfs.
* @clkrate_change_pending: Flag indicating the pending DSI clock re-enabling.
* @clock_info: Clock sourcing for DSI display.
@@ -225,7 +227,9 @@ struct dsi_display {
u32 video_master_idx;
/* dynamic DSI clock info*/
u32 cached_clk_rate;
u32 dyn_bit_clk;
bool dyn_bit_clk_pending;
u32 cached_clk_rate;
atomic_t clkrate_change_pending;
struct dsi_display_clk_info clock_info;
@@ -776,4 +780,21 @@ int dsi_display_get_panel_vfp(void *display,
*/
int dsi_display_dump_clks_state(struct dsi_display *display);
/**
* dsi_display_update_dyn_bit_clk() - update mode timing to compensate for dynamic bit clock
* @display: Handle to display
* @mode: Mode to be updated
* Return: Zero on Success
*/
int dsi_display_update_dyn_bit_clk(struct dsi_display *display, struct dsi_display_mode *mode);
/**
* dsi_display_restore_bit_clk() - restore mode bit clock rate value from dynamic bit clock
* @display: Handle to display
* @mode: Mode to be updated
* Return: Zero on Success
*/
int dsi_display_restore_bit_clk(struct dsi_display *display, struct dsi_display_mode *mode);
#endif /* _DSI_DISPLAY_H_ */

Переглянути файл

@@ -342,7 +342,9 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode)
{
struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
int rc = 0;
struct dsi_bridge *c_bridge = NULL;
struct dsi_display *display;
struct drm_connector *conn;
struct sde_connector_state *conn_state;
@@ -351,6 +353,18 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
return;
}
c_bridge = to_dsi_bridge(bridge);
if (!c_bridge) {
DSI_ERR("invalid dsi bridge\n");
return;
}
display = c_bridge->display;
if (!display || !display->drm_conn || !display->drm_conn->state) {
DSI_ERR("invalid display\n");
return;
}
memset(&(c_bridge->dsi_mode), 0x0, sizeof(struct dsi_display_mode));
convert_to_dsi_mode(adjusted_mode, &(c_bridge->dsi_mode));
conn = sde_encoder_get_connector(bridge->dev, bridge->encoder);
@@ -366,9 +380,11 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
msm_parse_mode_priv_info(&conn_state->msm_mode,
&(c_bridge->dsi_mode));
/* restore bit_clk_rate also for dynamic clk use cases */
c_bridge->dsi_mode.timing.clk_rate_hz =
dsi_drm_find_bit_clk_rate(c_bridge->display, adjusted_mode);
rc = dsi_display_restore_bit_clk(display, &c_bridge->dsi_mode);
if (rc) {
DSI_ERR("[%s] bit clk rate cannot be restored\n", display->name);
return;
}
DSI_DEBUG("clk_rate: %llu\n", c_bridge->dsi_mode.timing.clk_rate_hz);
}
@@ -436,6 +452,18 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
dsi_mode.timing.dsc_enabled = dsi_mode.priv_info->dsc_enabled;
dsi_mode.timing.dsc = &dsi_mode.priv_info->dsc;
rc = dsi_display_restore_bit_clk(display, &dsi_mode);
if (rc) {
DSI_ERR("[%s] bit clk rate cannot be restored\n", display->name);
return false;
}
rc = dsi_display_update_dyn_bit_clk(display, &dsi_mode);
if (rc) {
DSI_ERR("[%s] failed to update bit clock\n", display->name);
return false;
}
rc = dsi_display_validate_mode(c_bridge->display, &dsi_mode,
DSI_VALIDATE_FLAG_ALLOW_ADJUST);
if (rc) {
@@ -517,33 +545,6 @@ u32 dsi_drm_get_dfps_maxfps(void *display)
return dfps_maxfps;
}
u64 dsi_drm_find_bit_clk_rate(void *display,
const struct drm_display_mode *drm_mode)
{
int i = 0, count = 0;
struct dsi_display *dsi_display = display;
struct dsi_display_mode *dsi_mode;
u64 bit_clk_rate = 0;
if (!dsi_display || !drm_mode)
return 0;
dsi_display_get_mode_count(dsi_display, &count);
for (i = 0; i < count; i++) {
dsi_mode = &dsi_display->modes[i];
if ((dsi_mode->timing.v_active == drm_mode->vdisplay) &&
(dsi_mode->timing.h_active == drm_mode->hdisplay) &&
(dsi_mode->pixel_clk_khz == drm_mode->clock) &&
(dsi_mode->timing.refresh_rate == drm_mode_vrefresh(drm_mode))) {
bit_clk_rate = dsi_mode->timing.clk_rate_hz;
break;
}
}
return bit_clk_rate;
}
int dsi_conn_get_mode_info(struct drm_connector *connector,
const struct drm_display_mode *drm_mode,
struct msm_mode_info *mode_info,
@@ -578,6 +579,13 @@ int dsi_conn_get_mode_info(struct drm_connector *connector,
memcpy(&mode_info->topology, &dsi_mode->priv_info->topology,
sizeof(struct msm_display_topology));
if (dsi_mode->priv_info->bit_clk_list.count) {
mode_info->bit_clk_rates =
dsi_mode->priv_info->bit_clk_list.rates;
mode_info->bit_clk_count =
dsi_mode->priv_info->bit_clk_list.count;
}
if (dsi_mode->priv_info->dsc_enabled) {
mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_DSC;
mode_info->topology.comp_type = MSM_DISPLAY_COMPRESSION_DSC;
@@ -1296,3 +1304,25 @@ void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector,
mode_idx++;
}
}
int dsi_conn_set_dyn_bit_clk(struct drm_connector *connector, uint64_t value)
{
struct sde_connector *c_conn = NULL;
struct dsi_display *display;
if (!connector) {
DSI_ERR("invalid connector\n");
return -EINVAL;
}
c_conn = to_sde_connector(connector);
display = (struct dsi_display *) c_conn->display;
display->dyn_bit_clk = value;
display->dyn_bit_clk_pending = true;
SDE_EVT32(display->dyn_bit_clk);
DSI_DEBUG("update dynamic bit clock rate to %llu\n", display->dyn_bit_clk);
return 0;
}

Переглянути файл

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _DSI_DRM_H_
@@ -134,9 +134,6 @@ int dsi_conn_post_kickoff(struct drm_connector *connector,
void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
struct drm_display_mode *drm_mode);
u64 dsi_drm_find_bit_clk_rate(void *display,
const struct drm_display_mode *drm_mode);
/**
* dsi_conn_prepare_commit - program pre commit time features
* @display: Pointer to private display structure
@@ -154,4 +151,13 @@ int dsi_conn_prepare_commit(void *display,
void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector,
void *display);
/**
* dsi_conn_set_dyn_bit_clk - set target dynamic clock rate
* @connector: Pointer to drm connector structure
* @value: Target dynamic clock rate
* Returns: Zero on success
*/
int dsi_conn_set_dyn_bit_clk(struct drm_connector *connector,
uint64_t value);
#endif /* _DSI_DRM_H_ */

Переглянути файл

@@ -1326,13 +1326,48 @@ error:
return rc;
}
static int dsi_panel_parse_dyn_clk_list(struct dsi_display_mode *mode,
struct dsi_parser_utils *utils)
{
int i, rc = 0;
struct dyn_clk_list *bit_clk_list;
if (!mode || !mode->priv_info) {
DSI_ERR("invalid arguments\n");
return -EINVAL;
}
bit_clk_list = &mode->priv_info->bit_clk_list;
bit_clk_list->count = utils->count_u32_elems(utils->data, "qcom,dsi-dyn-clk-list");
if (bit_clk_list->count < 1)
return 0;
bit_clk_list->rates = kcalloc(bit_clk_list->count, sizeof(u32), GFP_KERNEL);
if (!bit_clk_list->rates) {
DSI_ERR("failed to allocate space for bit clock list\n");
return -ENOMEM;
}
rc = utils->read_u32_array(utils->data, "qcom,dsi-dyn-clk-list",
bit_clk_list->rates, bit_clk_list->count);
if (rc) {
DSI_ERR("failed to parse supported bit clk list, rc=%d\n", rc);
return -EINVAL;
}
for (i = 0; i < bit_clk_list->count; i++)
DSI_DEBUG("bit clk rate[%d]:%d\n", i, bit_clk_list->rates[i]);
return 0;
}
static int dsi_panel_parse_dyn_clk_caps(struct dsi_panel *panel)
{
int rc = 0;
bool supported = false;
struct dsi_dyn_clk_caps *dyn_clk_caps = &panel->dyn_clk_caps;
struct dsi_parser_utils *utils = &panel->utils;
const char *name = panel->name;
const char *type;
supported = utils->read_bool(utils->data, "qcom,dsi-dyn-clk-enable");
@@ -1342,28 +1377,6 @@ static int dsi_panel_parse_dyn_clk_caps(struct dsi_panel *panel)
return rc;
}
dyn_clk_caps->bit_clk_list_len = utils->count_u32_elems(utils->data,
"qcom,dsi-dyn-clk-list");
if (dyn_clk_caps->bit_clk_list_len < 1) {
DSI_ERR("[%s] failed to get supported bit clk list\n", name);
return -EINVAL;
}
dyn_clk_caps->bit_clk_list = kcalloc(dyn_clk_caps->bit_clk_list_len,
sizeof(u32), GFP_KERNEL);
if (!dyn_clk_caps->bit_clk_list)
return -ENOMEM;
rc = utils->read_u32_array(utils->data, "qcom,dsi-dyn-clk-list",
dyn_clk_caps->bit_clk_list,
dyn_clk_caps->bit_clk_list_len);
if (rc) {
DSI_ERR("[%s] failed to parse supported bit clk list\n", name);
return -EINVAL;
}
dyn_clk_caps->dyn_clk_support = true;
type = utils->get_property(utils->data,
@@ -4032,6 +4045,12 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
goto parse_fail;
}
if (panel->dyn_clk_caps.dyn_clk_support) {
rc = dsi_panel_parse_dyn_clk_list(mode, utils);
if (rc)
DSI_ERR("failed to parse dynamic clk rates, rc=%d\n", rc);
}
rc = dsi_panel_parse_dsc_params(mode, utils);
if (rc) {
DSI_ERR("failed to parse dsc params, rc=%d\n", rc);

Переглянути файл

@@ -97,8 +97,6 @@ struct dsi_qsync_capabilities {
struct dsi_dyn_clk_caps {
bool dyn_clk_support;
u32 *bit_clk_list;
u32 bit_clk_list_len;
enum dsi_dyn_clk_feature_type type;
bool maintain_const_fps;
};

Переглянути файл

@@ -211,6 +211,7 @@ enum msm_mdp_conn_property {
CONNECTOR_PROP_BL_SCALE,
CONNECTOR_PROP_SV_BL_SCALE,
CONNECTOR_PROP_SUPPORTED_COLORSPACES,
CONNECTOR_PROP_DYN_BIT_CLK,
/* enum/bitmask properties */
CONNECTOR_PROP_TOPOLOGY_NAME,
@@ -702,6 +703,8 @@ struct msm_display_topology {
* @mdp_transfer_time_us Specifies the mdp transfer time for command mode
* panels in microseconds.
* @allowed_mode_switches: bit mask to indicate supported mode switch.
* @bit_clk_rates: list of supported bit clock rates
* @bit_clk_count: number of supported bit clock rates
*/
struct msm_mode_info {
uint32_t frame_rate;
@@ -718,6 +721,8 @@ struct msm_mode_info {
u32 panel_mode_caps;
u32 mdp_transfer_time_us;
u32 allowed_mode_switches;
u32 *bit_clk_rates;
u32 bit_clk_count;
};
/**

Переглянути файл

@@ -292,6 +292,9 @@ static inline bool msm_is_private_mode_changed(
if (msm_is_mode_seamless_poms(msm_mode))
return true;
if (msm_is_mode_seamless_dyn_clk(msm_mode))
return true;
return false;
}

Переглянути файл

@@ -1595,6 +1595,15 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
c_conn->expected_panel_mode =
MSM_DISPLAY_CMD_MODE;
break;
case CONNECTOR_PROP_DYN_BIT_CLK:
if (!c_conn->ops.set_dyn_bit_clk)
break;
rc = c_conn->ops.set_dyn_bit_clk(connector, val);
if (rc)
SDE_ERROR_CONN(c_conn, "dynamic bit clock set failed, rc: %d", rc);
break;
default:
break;
}
@@ -2614,6 +2623,12 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn,
sde_kms_info_add_keyint(info, "bit_clk_rate",
mode_info.clk_rate);
if (mode_info.bit_clk_count > 0)
sde_kms_info_add_list(info, "dyn_bitclk_list",
mode_info.bit_clk_rates,
mode_info.bit_clk_count);
topology_idx = (int)sde_rm_get_topology_name(&sde_kms->rm,
mode_info.topology);
if (topology_idx < SDE_RM_TOPOLOGY_MAX) {
@@ -2788,6 +2803,12 @@ static int _sde_connector_install_properties(struct drm_device *dev,
CONNECTOR_PROP_HDR_INFO);
}
if (dsi_display && dsi_display->panel &&
dsi_display->panel->dyn_clk_caps.dyn_clk_support)
msm_property_install_range(&c_conn->property_info, "dyn_bit_clk",
0x0, 0, ~0, 0, CONNECTOR_PROP_DYN_BIT_CLK);
mutex_lock(&c_conn->base.dev->mode_config.mutex);
sde_connector_fill_modes(&c_conn->base,
dev->mode_config.max_width,

Переглянути файл

@@ -374,6 +374,14 @@ struct sde_connector_ops {
void (*set_allowed_mode_switch)(struct drm_connector *connector,
void *display);
/**
* set_dyn_bit_clk - set target dynamic clock rate
* @connector: Pointer to drm connector structure
* @value: Target dynamic clock rate
* Returns: Zero on success
*/
int (*set_dyn_bit_clk)(struct drm_connector *connector, uint64_t value);
/**
* get_qsync_min_fps - Get qsync min fps from qsync-min-fps-list
* @display: Pointer to private display structure
@@ -961,6 +969,14 @@ int sde_connector_set_blob_data(struct drm_connector *conn,
*/
int sde_connector_roi_v1_check_roi(struct drm_connector_state *conn_state);
/**
* sde_connector_set_dyn_bit_clk - set dynamic bit clock
* @conn: Pointer to drm_connector struct
* @value: Property value
* Returns: Zero on success
*/
int sde_connector_set_dyn_bit_clk(struct drm_connector *conn, uint64_t value);
/**
* sde_connector_schedule_status_work - manage ESD thread
* conn: Pointer to drm_connector struct

Переглянути файл

@@ -1736,6 +1736,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.cmd_receive = dsi_display_cmd_receive,
.install_properties = NULL,
.set_allowed_mode_switch = dsi_conn_set_allowed_mode_switch,
.set_dyn_bit_clk = dsi_conn_set_dyn_bit_clk,
.get_qsync_min_fps = dsi_display_get_qsync_min_fps,
.prepare_commit = dsi_conn_prepare_commit,
};
@@ -1756,6 +1757,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.get_panel_vfp = NULL,
.cmd_receive = NULL,
.install_properties = NULL,
.set_dyn_bit_clk = NULL,
.set_allowed_mode_switch = NULL,
};
static const struct sde_connector_ops dp_ops = {
@@ -1778,6 +1780,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.cmd_receive = NULL,
.install_properties = dp_connector_install_properties,
.set_allowed_mode_switch = NULL,
.set_dyn_bit_clk = NULL,
};
struct msm_display_info info;
struct drm_encoder *encoder;

Переглянути файл

@@ -611,6 +611,16 @@ void sde_kms_info_append_format(struct sde_kms_info *info,
*/
void sde_kms_info_stop(struct sde_kms_info *info);
/**
* sde_kms_info_add_list - add a space separated list to 'sde_kms_info'
* @info: Pointer to sde_kms_info structure
* @key: Pointer to key string
* @item: Pointer to array of integer values
* @size: Number of integers to parse
*/
void sde_kms_info_add_list(struct sde_kms_info *info,
const char *key, uint32_t *item, size_t size);
/**
* sde_kms_rect_intersect - intersect two rectangles
* @r1: first rectangle

Переглянути файл

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "sde-kms_utils:[%s] " fmt, __func__
@@ -91,6 +91,28 @@ void sde_kms_info_append(struct sde_kms_info *info,
}
}
void sde_kms_info_add_list(struct sde_kms_info *info, const char *key, uint32_t *value, size_t size)
{
uint32_t i, len;
if (!info || !key || !value || !size)
return;
sde_kms_info_start(info, key);
for (i = 0; i < size; i++) {
len = scnprintf(info->data + info->staged_len,
SDE_KMS_INFO_MAX_SIZE - info->len, "%d ",
value[i]);
/* check if snprintf truncated the string */
if ((info->staged_len + len) < SDE_KMS_INFO_MAX_SIZE) {
info->staged_len += len;
info->start = false;
}
}
sde_kms_info_stop(info);
}
void sde_kms_info_append_format(struct sde_kms_info *info,
uint32_t pixel_format,
uint64_t modifier)