drm/msm/dp: add support for HDR10+
Add support for sending HDR10+ VSIF formatted dynamic metadata
to compatible external displays via DP protocol's secondary
data packets.
Change-Id: I24e90eb9b5273f13aa9dbc24bbe3551bb8f51be5
Signed-off-by: Steve Cohen <cohens@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 4cacdea..f1ba16b 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -64,6 +64,11 @@
{0xFF, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
};
+enum dp_flush_bit {
+ DP_PPS_FLUSH,
+ DP_DHDR_FLUSH,
+};
+
struct dp_catalog_io {
struct dp_io_data *dp_ahb;
struct dp_io_data *dp_aux;
@@ -572,14 +577,16 @@
DUMP_PREFIX_NONE, 16, 4, buf, off, false);
}
-static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en)
+static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
+ u32 dhdr_max_pkts)
{
struct dp_catalog_private *catalog;
struct dp_io_data *io_data;
- u32 cfg, cfg2, misc;
+ u32 cfg, cfg2, cfg4, misc;
u32 sdp_cfg_off = 0;
u32 sdp_cfg2_off = 0;
u32 sdp_cfg3_off = 0;
+ u32 sdp_cfg4_off = 0;
u32 misc1_misc0_off = 0;
if (!panel) {
@@ -599,6 +606,7 @@
sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG;
sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2;
sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3;
+ sdp_cfg4_off = MMSS_DP1_SDP_CFG4 - MMSS_DP_SDP_CFG4;
misc1_misc0_off = DP1_MISC1_MISC0 - DP_MISC1_MISC0;
}
@@ -620,6 +628,13 @@
dp_write(catalog->exe_mode, io_data,
MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
+ /* DHDR_EN, DHDR_PACKET_LIMIT */
+ if (dhdr_max_pkts) {
+ cfg4 = (dhdr_max_pkts << 1) | BIT(0);
+ dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4
+ + sdp_cfg4_off, cfg4);
+ }
+
dp_catalog_panel_setup_vsc_sdp(panel);
dp_catalog_panel_setup_infoframe_sdp(panel);
@@ -641,6 +656,11 @@
dp_write(catalog->exe_mode, io_data,
MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
+ /* DHDR_EN, DHDR_PACKET_LIMIT */
+ cfg4 = 0;
+ dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4
+ + sdp_cfg4_off, cfg4);
+
/* switch back to MSA */
misc &= ~BIT(14);
@@ -1192,7 +1212,8 @@
reg, panel->stream_id);
}
-static void dp_catalog_panel_pps_flush(struct dp_catalog_panel *panel)
+static void dp_catalog_panel_dp_flush(struct dp_catalog_panel *panel,
+ enum dp_flush_bit flush_bit)
{
struct dp_catalog_private *catalog;
struct dp_io_data *io_data;
@@ -1217,12 +1238,47 @@
offset = MMSS_DP1_FLUSH - MMSS_DP_FLUSH;
dp_flush = dp_read(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset);
- dp_flush |= BIT(0);
+ dp_flush |= BIT(flush_bit);
dp_write(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset, dp_flush);
+}
+static void dp_catalog_panel_pps_flush(struct dp_catalog_panel *panel)
+{
+ dp_catalog_panel_dp_flush(panel, DP_PPS_FLUSH);
pr_debug("pps flush for stream:%d\n", panel->stream_id);
}
+static void dp_catalog_panel_dhdr_flush(struct dp_catalog_panel *panel)
+{
+ dp_catalog_panel_dp_flush(panel, DP_DHDR_FLUSH);
+ pr_debug("dhdr flush for stream:%d\n", panel->stream_id);
+}
+
+
+static bool dp_catalog_panel_dhdr_busy(struct dp_catalog_panel *panel)
+{
+ struct dp_catalog_private *catalog;
+ struct dp_io_data *io_data;
+ u32 dp_flush, offset;
+
+ if (panel->stream_id >= DP_STREAM_MAX) {
+ pr_err("invalid stream_id:%d\n", panel->stream_id);
+ return false;
+ }
+
+ catalog = dp_catalog_get_priv(panel);
+ io_data = catalog->io.dp_link;
+
+ if (panel->stream_id == DP_STREAM_0)
+ offset = 0;
+ else
+ offset = MMSS_DP1_FLUSH - MMSS_DP_FLUSH;
+
+ dp_flush = dp_read(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset);
+
+ return dp_flush & BIT(DP_DHDR_FLUSH) ? true : false;
+}
+
static void dp_catalog_ctrl_reset(struct dp_catalog_ctrl *ctrl)
{
u32 sw_reset;
@@ -2479,6 +2535,8 @@
.config_dto = dp_catalog_panel_config_dto,
.dsc_cfg = dp_catalog_panel_dsc_cfg,
.pps_flush = dp_catalog_panel_pps_flush,
+ .dhdr_flush = dp_catalog_panel_dhdr_flush,
+ .dhdr_busy = dp_catalog_panel_dhdr_busy,
};
if (!dev || !parser) {
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 1ef4f23..9d536b4 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -217,7 +217,8 @@
struct dp_dsc_cfg_data dsc;
int (*timing_cfg)(struct dp_catalog_panel *panel);
- void (*config_hdr)(struct dp_catalog_panel *panel, bool en);
+ void (*config_hdr)(struct dp_catalog_panel *panel, bool en,
+ u32 dhdr_max_pkts);
void (*tpg_config)(struct dp_catalog_panel *panel, bool enable);
void (*config_spd)(struct dp_catalog_panel *panel);
void (*config_misc)(struct dp_catalog_panel *panel);
@@ -228,6 +229,8 @@
void (*config_dto)(struct dp_catalog_panel *panel, bool ack);
void (*dsc_cfg)(struct dp_catalog_panel *panel);
void (*pps_flush)(struct dp_catalog_panel *panel);
+ void (*dhdr_flush)(struct dp_catalog_panel *panel);
+ bool (*dhdr_busy)(struct dp_catalog_panel *panel);
};
struct dp_catalog;
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index bc9eddc..75a2f16 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -944,6 +944,7 @@
y_frac_enum = (u32)((temp1 == temp2) ? temp1 : temp1 + 1);
+ panel->mst_target_sc = raw_target_sc;
*p_x_int = x_int;
*p_y_frac_enum = y_frac_enum;
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 1145858..e5f1b3e 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -1279,7 +1279,7 @@
len = -EINVAL;
}
- debug->panel->setup_hdr(debug->panel, &c_state->hdr_meta);
+ debug->panel->setup_hdr(debug->panel, &c_state->hdr_meta, false, 0);
end:
return len;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 13acf31..ccfa611f 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1497,7 +1497,7 @@
struct dp_panel *dp_panel)
{
dp_panel->spd_config(dp_panel);
- dp_panel->setup_hdr(dp_panel, NULL);
+ dp_panel->setup_hdr(dp_panel, NULL, false, 0);
}
static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
@@ -1903,23 +1903,27 @@
}
static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
- struct drm_msm_ext_hdr_metadata *hdr)
+ struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update)
{
- int rc = 0;
- struct dp_display_private *dp;
struct dp_panel *dp_panel;
+ struct dp_display_private *dp;
+ u64 core_clk_rate;
if (!dp_display || !panel) {
pr_err("invalid input\n");
return -EINVAL;
}
- dp = container_of(dp_display, struct dp_display_private, dp_display);
dp_panel = panel;
+ dp = container_of(dp_display, struct dp_display_private, dp_display);
- rc = dp_panel->setup_hdr(dp_panel, hdr);
+ core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk");
+ if (!core_clk_rate) {
+ pr_err("invalid rate for core_clk\n");
+ return -EINVAL;
+ }
- return rc;
+ return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update, core_clk_rate);
}
static int dp_display_create_workqueue(struct dp_display_private *dp)
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index 00adbbd..410cee7 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -87,7 +87,8 @@
struct dp_debug *(*get_debug)(struct dp_display *dp_display);
void (*post_open)(struct dp_display *dp_display);
int (*config_hdr)(struct dp_display *dp_display, void *panel,
- struct drm_msm_ext_hdr_metadata *hdr_meta);
+ struct drm_msm_ext_hdr_metadata *hdr_meta,
+ bool dhdr_update);
int (*post_init)(struct dp_display *dp_display);
int (*mst_install)(struct dp_display *dp_display,
struct dp_mst_drm_install_info *mst_install_info);
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 40406cd..9b3bb24 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -324,7 +324,8 @@
return -EINVAL;
}
- return dp->config_hdr(dp, sde_conn->drv_panel, &c_state->hdr_meta);
+ return dp->config_hdr(dp, sde_conn->drv_panel, &c_state->hdr_meta,
+ c_state->dyn_hdr_meta.dynamic_hdr_update);
}
int dp_connector_post_init(struct drm_connector *connector, void *display)
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 2a9bbb8..a486a32 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -17,6 +17,7 @@
#define VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED BIT(3)
#define VSC_EXT_VESA_SDP_SUPPORTED BIT(4)
#define VSC_EXT_VESA_SDP_CHAINING_SUPPORTED BIT(5)
+#define SEQ_INCREMENT_FOR_CHAINED_PACKETS BIT(6)
enum dp_panel_hdr_pixel_encoding {
RGB,
@@ -99,6 +100,17 @@
static const u8 product_desc[16] = {83, 110, 97, 112, 100, 114, 97, 103,
111, 110, 0, 0, 0, 0, 0, 0};
+struct dp_dhdr_maxpkt_calc_input {
+ u32 mdp_clk;
+ u32 lclk;
+ u32 pclk;
+ u32 h_active;
+ u32 nlanes;
+ s64 mst_target_sc;
+ bool mst_en;
+ bool fec_en;
+};
+
struct tu_algo_data {
s64 lclk_fp;
s64 pclk_fp;
@@ -2362,8 +2374,10 @@
connector->hdr_avg_luminance = 0;
connector->hdr_min_luminance = 0;
connector->hdr_supported = false;
+ connector->hdr_plus_app_ver = 0;
memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
+ memset(&c_state->dyn_hdr_meta, 0, sizeof(c_state->dyn_hdr_meta));
return rc;
}
@@ -2409,12 +2423,97 @@
(panel->minor >= 4 || panel->vscext_supported);
}
-static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
- struct drm_msm_ext_hdr_metadata *hdr_meta)
+static u32 dp_panel_calc_dhdr_pkt_limit(struct dp_panel *dp_panel,
+ struct dp_dhdr_maxpkt_calc_input *input)
{
- int rc = 0;
+ s64 mdpclk_fp = drm_fixp_from_fraction(input->mdp_clk, 1000000);
+ s64 lclk_fp = drm_fixp_from_fraction(input->lclk, 1000);
+ s64 pclk_fp = drm_fixp_from_fraction(input->pclk, 1000);
+ s64 nlanes_fp = drm_int2fixp(input->nlanes);
+ s64 target_sc = input->mst_target_sc;
+ s64 hactive_fp = drm_int2fixp(input->h_active);
+ const s64 i1_fp = DRM_FIXED_ONE;
+ const s64 i2_fp = drm_int2fixp(2);
+ const s64 i10_fp = drm_int2fixp(10);
+ const s64 i56_fp = drm_int2fixp(56);
+ const s64 i64_fp = drm_int2fixp(64);
+ s64 mst_bw_fp = i1_fp;
+ s64 fec_factor_fp = i1_fp;
+ s64 mst_bw64_fp, mst_bw64_ceil_fp, nlanes56_fp;
+ u32 f1, f2, f3, f4, f5, deploy_period, target_period;
+ s64 f3_f5_slot_fp;
+ u32 calc_pkt_limit;
+ const u32 max_pkt_limit = 64;
+
+ if (input->fec_en && input->mst_en)
+ fec_factor_fp = drm_fixp_from_fraction(64000, 65537);
+
+ if (input->mst_en)
+ mst_bw_fp = drm_fixp_div(target_sc, i64_fp);
+
+ f1 = drm_fixp2int_ceil(drm_fixp_div(drm_fixp_mul(i10_fp, lclk_fp),
+ mdpclk_fp));
+ f2 = drm_fixp2int_ceil(drm_fixp_div(drm_fixp_mul(i2_fp, lclk_fp),
+ mdpclk_fp)) + drm_fixp2int_ceil(drm_fixp_div(
+ drm_fixp_mul(i1_fp, lclk_fp), mdpclk_fp));
+
+ mst_bw64_fp = drm_fixp_mul(mst_bw_fp, i64_fp);
+ if (drm_fixp2int(mst_bw64_fp) == 0)
+ f3_f5_slot_fp = drm_fixp_div(i1_fp, drm_int2fixp(
+ drm_fixp2int_ceil(drm_fixp_div(
+ i1_fp, mst_bw64_fp))));
+ else
+ f3_f5_slot_fp = drm_int2fixp(drm_fixp2int(mst_bw_fp));
+
+ mst_bw64_ceil_fp = drm_int2fixp(drm_fixp2int_ceil(mst_bw64_fp));
+ f3 = drm_fixp2int(drm_fixp_mul(drm_int2fixp(drm_fixp2int(
+ drm_fixp_div(i2_fp, f3_f5_slot_fp)) + 1),
+ (i64_fp - mst_bw64_ceil_fp))) + 2;
+
+ if (!input->mst_en) {
+ f4 = 1 + drm_fixp2int(drm_fixp_div(drm_int2fixp(50),
+ nlanes_fp)) + drm_fixp2int(drm_fixp_div(
+ nlanes_fp, i2_fp));
+ f5 = 0;
+ } else {
+ f4 = 0;
+ nlanes56_fp = drm_fixp_div(i56_fp, nlanes_fp);
+ f5 = drm_fixp2int(drm_fixp_mul(drm_int2fixp(drm_fixp2int(
+ drm_fixp_div(i1_fp + nlanes56_fp,
+ f3_f5_slot_fp)) + 1), (i64_fp -
+ mst_bw64_ceil_fp + i1_fp + nlanes56_fp)));
+ }
+
+ deploy_period = f1 + f2 + f3 + f4 + f5 + 19;
+ target_period = drm_fixp2int(drm_fixp_mul(fec_factor_fp, drm_fixp_mul(
+ hactive_fp, drm_fixp_div(lclk_fp, pclk_fp))));
+
+ calc_pkt_limit = target_period / deploy_period;
+
+ pr_debug("input: %d, %d, %d, %d, %d, 0x%llx, %d, %d\n",
+ input->mdp_clk, input->lclk, input->pclk, input->h_active,
+ input->nlanes, input->mst_target_sc, input->mst_en ? 1 : 0,
+ input->fec_en ? 1 : 0);
+ pr_debug("factors: %d, %d, %d, %d, %d\n", f1, f2, f3, f4, f5);
+ pr_debug("d_p: %d, t_p: %d, maxPkts: %d%s\n", deploy_period,
+ target_period, calc_pkt_limit, calc_pkt_limit > max_pkt_limit ?
+ " CAPPED" : "");
+
+ if (calc_pkt_limit > max_pkt_limit)
+ calc_pkt_limit = max_pkt_limit;
+
+ pr_debug("packet limit per line = %d\n", calc_pkt_limit);
+ return calc_pkt_limit;
+}
+
+static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
+ struct drm_msm_ext_hdr_metadata *hdr_meta,
+ bool dhdr_update, u64 core_clk_rate)
+{
+ int rc = 0, max_pkts = 0;
struct dp_panel_private *panel;
struct dp_catalog_hdr_data *hdr;
+ struct dp_dhdr_maxpkt_calc_input input;
if (!dp_panel) {
pr_err("invalid input\n");
@@ -2470,9 +2569,29 @@
else
memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta));
cached:
+ if (dhdr_update) {
+ hdr->vscext_header_byte2 |= SEQ_INCREMENT_FOR_CHAINED_PACKETS;
+
+ input.mdp_clk = core_clk_rate;
+ input.lclk = dp_panel->link_info.rate;
+ input.nlanes = dp_panel->link_info.num_lanes;
+ input.pclk = dp_panel->pinfo.pixel_clk_khz;
+ input.h_active = dp_panel->pinfo.h_active;
+ input.mst_target_sc = dp_panel->mst_target_sc;
+ input.mst_en = dp_panel->mst_state;
+ input.fec_en = dp_panel->fec_en;
+ max_pkts = dp_panel_calc_dhdr_pkt_limit(dp_panel, &input);
+ }
+
if (panel->panel_on) {
panel->catalog->stream_id = dp_panel->stream_id;
- panel->catalog->config_hdr(panel->catalog, panel->hdr_state);
+ panel->catalog->config_hdr(panel->catalog, panel->hdr_state,
+ max_pkts);
+ if (dhdr_update) {
+ panel->catalog->dhdr_flush(panel->catalog);
+ hdr->vscext_header_byte2 &=
+ ~SEQ_INCREMENT_FOR_CHAINED_PACKETS;
+ }
}
end:
return rc;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 8bcce99..90d5346 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -101,6 +101,7 @@
u32 vic;
u32 max_pclk_khz;
+ s64 mst_target_sc;
/* debug */
u32 max_bw_code;
@@ -145,7 +146,8 @@
int (*set_edid)(struct dp_panel *dp_panel, u8 *edid);
int (*set_dpcd)(struct dp_panel *dp_panel, u8 *dpcd);
int (*setup_hdr)(struct dp_panel *dp_panel,
- struct drm_msm_ext_hdr_metadata *hdr_meta);
+ struct drm_msm_ext_hdr_metadata *hdr_meta,
+ bool dhdr_update, u64 core_clk_rate);
void (*tpg_config)(struct dp_panel *dp_panel, bool enable);
int (*spd_config)(struct dp_panel *dp_panel);
bool (*hdr_supported)(struct dp_panel *dp_panel);
diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c
index 0f32a10..d6f2f41 100644
--- a/drivers/gpu/drm/msm/dp/dp_power.c
+++ b/drivers/gpu/drm/msm/dp/dp_power.c
@@ -544,6 +544,44 @@
return rc;
}
+static u64 dp_power_clk_get_rate(struct dp_power *dp_power, char *clk_name)
+{
+ size_t i;
+ enum dp_pm_type j;
+ struct dss_module_power *mp;
+ struct dp_power_private *power;
+ bool clk_found = false;
+ u64 rate = 0;
+
+ if (!clk_name) {
+ pr_err("invalid pointer for clk_name\n");
+ return 0;
+ }
+
+ power = container_of(dp_power, struct dp_power_private, dp_power);
+ mp = &power->phandle->mp;
+ for (i = 0; i < mp->num_clk; i++) {
+ if (!strcmp(mp->clk_config[i].clk_name, clk_name)) {
+ rate = clk_get_rate(mp->clk_config[i].clk);
+ clk_found = true;
+ break;
+ }
+ }
+
+ for (j = DP_CORE_PM; j < DP_MAX_PM && !clk_found; j++) {
+ mp = &power->parser->mp[j];
+ for (i = 0; i < mp->num_clk; i++) {
+ if (!strcmp(mp->clk_config[i].clk_name, clk_name)) {
+ rate = clk_get_rate(mp->clk_config[i].clk);
+ clk_found = true;
+ break;
+ }
+ }
+ }
+
+ return rate;
+}
+
static int dp_power_init(struct dp_power *dp_power, bool flip)
{
int rc = 0;
@@ -660,6 +698,7 @@
dp_power->deinit = dp_power_deinit;
dp_power->clk_enable = dp_power_clk_enable;
dp_power->set_pixel_clk_parent = dp_power_set_pixel_clk_parent;
+ dp_power->clk_get_rate = dp_power_clk_get_rate;
dp_power->power_client_init = dp_power_client_init;
dp_power->power_client_deinit = dp_power_client_deinit;
diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h
index 3f8943d..bd58166 100644
--- a/drivers/gpu/drm/msm/dp/dp_power.h
+++ b/drivers/gpu/drm/msm/dp/dp_power.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*/
#ifndef _DP_POWER_H_
@@ -16,6 +16,7 @@
* @deinit: turns off the regulators/core clocks/GPIOs/pinctrl
* @clk_enable: enable/disable the DP clocks
* @set_pixel_clk_parent: set the parent of DP pixel clock
+ * @clk_get_rate: get the current rate for provided clk_name
*/
struct dp_power {
int (*init)(struct dp_power *power, bool flip);
@@ -23,6 +24,7 @@
int (*clk_enable)(struct dp_power *power, enum dp_pm_type pm_type,
bool enable);
int (*set_pixel_clk_parent)(struct dp_power *power, u32 stream_id);
+ u64 (*clk_get_rate)(struct dp_power *power, char *clk_name);
int (*power_client_init)(struct dp_power *power,
struct sde_power_handle *phandle);
void (*power_client_deinit)(struct dp_power *power);
diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
index b2ff651..697d50d 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -132,6 +132,7 @@
#define MMSS_DP_SDP_CFG (0x00000228)
#define MMSS_DP_SDP_CFG2 (0x0000022C)
#define MMSS_DP_SDP_CFG3 (0x0000024C)
+#define MMSS_DP_SDP_CFG4 (0x000004EC)
#define MMSS_DP_AUDIO_TIMESTAMP_0 (0x00000230)
#define MMSS_DP_AUDIO_TIMESTAMP_1 (0x00000234)
@@ -212,6 +213,7 @@
#define MMSS_DP1_SDP_CFG (0x000004E0)
#define MMSS_DP1_SDP_CFG2 (0x000004E4)
#define MMSS_DP1_SDP_CFG3 (0x000004E8)
+#define MMSS_DP1_SDP_CFG4 (0x000004F0)
#define DP1_COMPRESSION_MODE_CTRL (0x00000560)
#define DP1_PPS_HB_0_3 (0x00000564)