Merge "disp: msm: dp: add colorspace property for MSM DP"

This commit is contained in:
qctecmdr
2019-07-28 01:12:00 -07:00
committed by Gerrit - the friendly Code Review server
13 changed files with 640 additions and 165 deletions

View File

@@ -189,6 +189,98 @@ struct tu_algo_data {
s64 ratio;
};
/**
* Mapper function which outputs colorimetry and dynamic range
* to be used for a given colorspace value when the vsc sdp
* packets are used to change the colorimetry.
*/
static void get_sdp_colorimetry_range(struct dp_panel_private *panel,
u32 colorspace, u32 *colorimetry, u32 *dynamic_range)
{
u32 cc;
/*
* Some rules being used for assignment of dynamic
* range for colorimetry using SDP:
*
* 1) If compliance test is ongoing return sRGB with
* CEA primaries
* 2) For BT2020 cases, dynamic range shall be CEA
* 3) For DCI-P3 cases, as per HW team dynamic range
* shall be VESA for RGB and CEA for YUV content
* Hence defaulting to RGB and picking VESA
* 4) Default shall be sRGB with VESA
*/
cc = panel->link->get_colorimetry_config(panel->link);
if (cc) {
*colorimetry = sRGB;
*dynamic_range = CEA;
return;
}
switch (colorspace) {
case DRM_MODE_COLORIMETRY_BT2020_RGB:
*colorimetry = ITU_R_BT_2020_RGB;
*dynamic_range = CEA;
break;
case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65:
case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER:
*colorimetry = DCI_P3;
*dynamic_range = VESA;
break;
default:
*colorimetry = sRGB;
*dynamic_range = VESA;
}
}
/**
* Mapper function which outputs colorimetry to be used for a
* given colorspace value when misc field of MSA is used to
* change the colorimetry. Currently only RGB formats have been
* added. This API will be extended to YUV once its supported on DP.
*/
static u8 get_misc_colorimetry_val(struct dp_panel_private *panel,
u32 colorspace)
{
u8 colorimetry;
u32 cc;
cc = panel->link->get_colorimetry_config(panel->link);
/*
* If there is a non-zero value then compliance test-case
* is going on, otherwise we can honor the colorspace setting
*/
if (cc)
return cc;
switch (colorspace) {
case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65:
case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER:
colorimetry = 0x7;
break;
case DRM_MODE_DP_COLORIMETRY_SRGB:
colorimetry = 0x4;
break;
case DRM_MODE_DP_COLORIMETRY_RGB_WIDE_GAMUT:
colorimetry = 0x3;
break;
case DRM_MODE_DP_COLORIMETRY_SCRGB:
colorimetry = 0xb;
break;
case DRM_MODE_COLORIMETRY_OPRGB:
colorimetry = 0xc;
break;
default:
colorimetry = 0;
}
return colorimetry;
}
static int _tu_param_compare(s64 a, s64 b)
{
u32 a_int, a_frac, a_sign;
@@ -2485,7 +2577,11 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel, u32 flags)
{
int rc = 0;
struct dp_panel_private *panel;
struct dp_catalog_hdr_data *hdr;
struct drm_msm_ext_hdr_metadata *hdr_meta;
struct dp_sdp_header *dhdr_vsif_sdp;
struct sde_connector *sde_conn;
struct dp_sdp_header *shdr_if_sdp;
struct dp_catalog_vsc_sdp_colorimetry *vsc_colorimetry;
struct drm_connector *connector;
struct sde_connector_state *c_state;
@@ -2500,17 +2596,26 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel, u32 flags)
}
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
hdr = &panel->catalog->hdr_data;
hdr_meta = &panel->catalog->hdr_meta;
dhdr_vsif_sdp = &panel->catalog->dhdr_vsif_sdp;
shdr_if_sdp = &panel->catalog->shdr_if_sdp;
vsc_colorimetry = &panel->catalog->vsc_colorimetry;
if (!panel->custom_edid && dp_panel->edid_ctrl->edid)
sde_free_edid((void **)&dp_panel->edid_ctrl);
dp_panel_set_stream_info(dp_panel, DP_STREAM_MAX, 0, 0, 0, 0);
memset(&dp_panel->pinfo, 0, sizeof(dp_panel->pinfo));
memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta));
memset(hdr_meta, 0, sizeof(struct drm_msm_ext_hdr_metadata));
memset(dhdr_vsif_sdp, 0, sizeof(struct dp_sdp_header));
memset(shdr_if_sdp, 0, sizeof(struct dp_sdp_header));
memset(vsc_colorimetry, 0,
sizeof(struct dp_catalog_vsc_sdp_colorimetry));
panel->panel_on = false;
connector = dp_panel->connector;
sde_conn = to_sde_connector(connector);
c_state = to_sde_connector_state(connector->state);
connector->hdr_eotf = 0;
@@ -2521,6 +2626,8 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel, u32 flags)
connector->hdr_supported = false;
connector->hdr_plus_app_ver = 0;
sde_conn->colorspace_updated = false;
memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
memset(&c_state->dyn_hdr_meta, 0, sizeof(c_state->dyn_hdr_meta));
@@ -2651,14 +2758,133 @@ static u32 dp_panel_calc_dhdr_pkt_limit(struct dp_panel *dp_panel,
return calc_pkt_limit;
}
static void dp_panel_setup_colorimetry_sdp(struct dp_panel *dp_panel,
u32 cspace)
{
struct dp_panel_private *panel;
struct dp_catalog_vsc_sdp_colorimetry *hdr_colorimetry;
u8 bpc;
u32 colorimetry = 0;
u32 dynamic_range = 0;
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
hdr_colorimetry = &panel->catalog->vsc_colorimetry;
hdr_colorimetry->header.HB0 = 0x00;
hdr_colorimetry->header.HB1 = 0x07;
hdr_colorimetry->header.HB2 = 0x05;
hdr_colorimetry->header.HB3 = 0x13;
get_sdp_colorimetry_range(panel, cspace, &colorimetry,
&dynamic_range);
/* VSC SDP Payload for DB16 */
hdr_colorimetry->data[16] = (RGB << 4) | colorimetry;
/* VSC SDP Payload for DB17 */
hdr_colorimetry->data[17] = (dynamic_range << 7);
bpc = (dp_panel->pinfo.bpp / 3);
switch (bpc) {
default:
case 10:
hdr_colorimetry->data[17] |= BIT(1);
break;
case 8:
hdr_colorimetry->data[17] |= BIT(0);
break;
case 6:
hdr_colorimetry->data[17] |= 0;
break;
}
/* VSC SDP Payload for DB18 */
hdr_colorimetry->data[18] = GRAPHICS;
}
static void dp_panel_setup_hdr_if(struct dp_panel_private *panel)
{
struct dp_sdp_header *shdr_if;
shdr_if = &panel->catalog->shdr_if_sdp;
shdr_if->HB0 = 0x00;
shdr_if->HB1 = 0x87;
shdr_if->HB2 = 0x1D;
shdr_if->HB3 = 0x13 << 2;
}
static void dp_panel_setup_dhdr_vsif(struct dp_panel_private *panel)
{
struct dp_sdp_header *dhdr_vsif;
dhdr_vsif = &panel->catalog->dhdr_vsif_sdp;
dhdr_vsif->HB0 = 0x00;
dhdr_vsif->HB1 = 0x81;
dhdr_vsif->HB2 = 0x1D;
dhdr_vsif->HB3 = 0x13 << 2;
}
static void dp_panel_setup_misc_colorimetry(struct dp_panel *dp_panel,
u32 colorspace)
{
struct dp_panel_private *panel;
struct dp_catalog_panel *catalog;
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
catalog = panel->catalog;
catalog->misc_val &= ~0x1e;
catalog->misc_val |= (get_misc_colorimetry_val(panel,
colorspace) << 1);
}
static int dp_panel_set_colorspace(struct dp_panel *dp_panel,
u32 colorspace)
{
int rc = 0;
struct dp_panel_private *panel;
if (!dp_panel) {
pr_err("invalid input\n");
rc = -EINVAL;
goto end;
}
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
if (panel->vsc_supported)
dp_panel_setup_colorimetry_sdp(dp_panel,
colorspace);
else
dp_panel_setup_misc_colorimetry(dp_panel,
colorspace);
/*
* During the first frame update panel_on will be false and
* the colorspace will be cached in the connector's state which
* shall be used in the dp_panel_hw_cfg
*/
if (panel->panel_on) {
DP_DEBUG("panel is ON programming colorspace\n");
rc = panel->catalog->set_colorspace(panel->catalog,
panel->vsc_supported);
}
end:
return rc;
}
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)
bool dhdr_update, u64 core_clk_rate, bool flush)
{
int rc = 0, max_pkts = 0;
struct dp_panel_private *panel;
struct dp_catalog_hdr_data *hdr;
struct dp_dhdr_maxpkt_calc_input input;
struct drm_msm_ext_hdr_metadata *catalog_hdr_meta;
if (!dp_panel) {
DP_ERR("invalid input\n");
@@ -2667,11 +2893,12 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
}
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
hdr = &panel->catalog->hdr_data;
catalog_hdr_meta = &panel->catalog->hdr_meta;
/* use cached meta data in case meta data not provided */
if (!hdr_meta) {
if (hdr->hdr_meta.hdr_state)
if (catalog_hdr_meta->hdr_state)
goto cached;
else
goto end;
@@ -2679,41 +2906,18 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
panel->hdr_state = hdr_meta->hdr_state;
hdr->vsc_header_byte0 = 0x00;
hdr->vsc_header_byte1 = 0x07;
hdr->vsc_header_byte2 = 0x05;
hdr->vsc_header_byte3 = 0x13;
dp_panel_setup_hdr_if(panel);
hdr->shdr_header_byte0 = 0x00;
hdr->shdr_header_byte1 = 0x87;
hdr->shdr_header_byte2 = 0x1D;
hdr->shdr_header_byte3 = 0x13 << 2;
/* VSC SDP Payload for DB16 */
hdr->pixel_encoding = RGB;
hdr->colorimetry = ITU_R_BT_2020_RGB;
/* VSC SDP Payload for DB17 */
hdr->dynamic_range = CEA;
/* VSC SDP Payload for DB18 */
hdr->content_type = GRAPHICS;
hdr->bpc = dp_panel->pinfo.bpp / 3;
hdr->version = 0x01;
hdr->length = 0x1A;
if (panel->hdr_state)
memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta));
else
memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta));
if (panel->hdr_state) {
memcpy(catalog_hdr_meta, hdr_meta,
sizeof(struct drm_msm_ext_hdr_metadata));
} else {
memset(catalog_hdr_meta, 0,
sizeof(struct drm_msm_ext_hdr_metadata));
}
cached:
if (dhdr_update) {
hdr->vscext_header_byte0 = 0x00;
hdr->vscext_header_byte1 = 0x81;
hdr->vscext_header_byte2 = 0x1D;
hdr->vscext_header_byte3 = 0x13 << 2;
dp_panel_setup_dhdr_vsif(panel);
input.mdp_clk = core_clk_rate;
input.lclk = dp_panel->link_info.rate;
@@ -2729,7 +2933,7 @@ cached:
if (panel->panel_on) {
panel->catalog->stream_id = dp_panel->stream_id;
panel->catalog->config_hdr(panel->catalog, panel->hdr_state,
max_pkts);
max_pkts, flush);
if (dhdr_update)
panel->catalog->dhdr_flush(panel->catalog);
}
@@ -2808,19 +3012,29 @@ static void dp_panel_config_misc(struct dp_panel *dp_panel)
{
struct dp_panel_private *panel;
struct dp_catalog_panel *catalog;
struct drm_connector *connector;
u32 misc_val;
u32 tb, cc;
u32 tb, cc, colorspace;
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
catalog = panel->catalog;
connector = dp_panel->connector;
cc = 0;
tb = panel->link->get_test_bits_depth(panel->link, dp_panel->pinfo.bpp);
cc = panel->link->get_colorimetry_config(panel->link);
colorspace = connector->state->colorspace;
cc = (get_misc_colorimetry_val(panel, colorspace) << 1);
misc_val = cc;
misc_val |= (tb << 5);
misc_val |= BIT(0); /* Configure clock to synchronous mode */
/* if VSC is supported then set bit 6 of MISC1 */
if (panel->vsc_supported)
misc_val |= BIT(14);
catalog->misc_val = misc_val;
catalog->config_misc(catalog);
}
@@ -2862,9 +3076,21 @@ static void dp_panel_resolution_info(struct dp_panel_private *panel)
panel->link->link_params.lane_count);
}
static void dp_panel_config_sdp(struct dp_panel *dp_panel,
bool en)
{
struct dp_panel_private *panel;
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
panel->catalog->stream_id = dp_panel->stream_id;
panel->catalog->config_sdp(panel->catalog, en);
}
static int dp_panel_hw_cfg(struct dp_panel *dp_panel, bool enable)
{
struct dp_panel_private *panel;
struct drm_connector *connector;
if (!dp_panel) {
DP_ERR("invalid input\n");
@@ -2878,15 +3104,23 @@ static int dp_panel_hw_cfg(struct dp_panel *dp_panel, bool enable)
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
panel->catalog->stream_id = dp_panel->stream_id;
connector = dp_panel->connector;
if (enable) {
dp_panel_config_ctrl(dp_panel);
dp_panel_config_misc(dp_panel);
dp_panel_config_msa(dp_panel);
if (panel->vsc_supported) {
dp_panel_setup_colorimetry_sdp(dp_panel,
connector->state->colorspace);
dp_panel_config_sdp(dp_panel, true);
}
dp_panel_config_dsc(dp_panel, enable);
dp_panel_config_tr_unit(dp_panel);
dp_panel_config_timing(dp_panel);
dp_panel_resolution_info(panel);
} else {
dp_panel_config_sdp(dp_panel, false);
}
panel->catalog->config_dto(panel->catalog, !enable);
@@ -3100,6 +3334,7 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in)
dp_panel->tpg_config = dp_panel_tpg_config;
dp_panel->spd_config = dp_panel_spd_config;
dp_panel->setup_hdr = dp_panel_setup_hdr;
dp_panel->set_colorspace = dp_panel_set_colorspace;
dp_panel->hdr_supported = dp_panel_hdr_supported;
dp_panel->set_stream_info = dp_panel_set_stream_info;
dp_panel->read_sink_status = dp_panel_read_sink_sts;