Merge "disp: msm: dp: add colorspace property for MSM DP"
This commit is contained in:
commit
60d59191c8
@ -6,7 +6,6 @@
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
||||
#include "dp_catalog.h"
|
||||
#include "dp_reg.h"
|
||||
@ -478,6 +477,29 @@ static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl)
|
||||
return dp_read(catalog->exe_mode, io_data, DP_HDCP_STATUS);
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_sdp_update(struct dp_catalog_panel *panel)
|
||||
{
|
||||
struct dp_catalog_private *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 sdp_cfg3_off = 0;
|
||||
|
||||
if (panel->stream_id >= DP_STREAM_MAX) {
|
||||
pr_err("invalid stream_id:%d\n", panel->stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (panel->stream_id == DP_STREAM_1)
|
||||
sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3;
|
||||
|
||||
catalog = dp_catalog_get_priv(panel);
|
||||
io_data = catalog->io.dp_link;
|
||||
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
|
||||
0x01);
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
|
||||
0x00);
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_setup_vsif_infoframe_sdp(
|
||||
struct dp_catalog_panel *panel)
|
||||
{
|
||||
@ -496,11 +518,11 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp(
|
||||
mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0;
|
||||
|
||||
catalog = dp_catalog_get_priv(panel);
|
||||
hdr = &panel->hdr_data.hdr_meta;
|
||||
hdr = &panel->hdr_meta;
|
||||
io_data = catalog->io.dp_link;
|
||||
|
||||
/* HEADER BYTE 1 */
|
||||
header = panel->hdr_data.vscext_header_byte1;
|
||||
header = panel->dhdr_vsif_sdp.HB1;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_1_BIT)
|
||||
| (parity << PARITY_BYTE_1_BIT));
|
||||
@ -510,7 +532,7 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp(
|
||||
off += sizeof(data);
|
||||
|
||||
/* HEADER BYTE 2 */
|
||||
header = panel->hdr_data.vscext_header_byte2;
|
||||
header = panel->dhdr_vsif_sdp.HB2;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_2_BIT)
|
||||
| (parity << PARITY_BYTE_2_BIT));
|
||||
@ -518,7 +540,7 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp(
|
||||
data);
|
||||
|
||||
/* HEADER BYTE 3 */
|
||||
header = panel->hdr_data.vscext_header_byte3;
|
||||
header = panel->dhdr_vsif_sdp.HB3;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_3_BIT)
|
||||
| (parity << PARITY_BYTE_3_BIT));
|
||||
@ -541,6 +563,8 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
|
||||
struct dp_io_data *io_data;
|
||||
u32 header, parity, data, mst_offset = 0;
|
||||
u8 buf[SZ_64], off = 0;
|
||||
u32 const version = 0x01;
|
||||
u32 const length = 0x1a;
|
||||
|
||||
if (panel->stream_id >= DP_STREAM_MAX) {
|
||||
DP_ERR("invalid stream_id:%d\n", panel->stream_id);
|
||||
@ -551,11 +575,11 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
|
||||
mst_offset = MMSS_DP1_GENERIC2_0 - MMSS_DP_GENERIC2_0;
|
||||
|
||||
catalog = dp_catalog_get_priv(panel);
|
||||
hdr = &panel->hdr_data.hdr_meta;
|
||||
hdr = &panel->hdr_meta;
|
||||
io_data = catalog->io.dp_link;
|
||||
|
||||
/* HEADER BYTE 1 */
|
||||
header = panel->hdr_data.shdr_header_byte1;
|
||||
header = panel->shdr_if_sdp.HB1;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_1_BIT)
|
||||
| (parity << PARITY_BYTE_1_BIT));
|
||||
@ -565,7 +589,7 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
|
||||
off += sizeof(data);
|
||||
|
||||
/* HEADER BYTE 2 */
|
||||
header = panel->hdr_data.shdr_header_byte2;
|
||||
header = panel->shdr_if_sdp.HB2;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_2_BIT)
|
||||
| (parity << PARITY_BYTE_2_BIT));
|
||||
@ -573,7 +597,7 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
|
||||
data);
|
||||
|
||||
/* HEADER BYTE 3 */
|
||||
header = panel->hdr_data.shdr_header_byte3;
|
||||
header = panel->shdr_if_sdp.HB3;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_3_BIT)
|
||||
| (parity << PARITY_BYTE_3_BIT));
|
||||
@ -584,8 +608,8 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
|
||||
memcpy(buf + off, &data, sizeof(data));
|
||||
off += sizeof(data);
|
||||
|
||||
data = panel->hdr_data.version;
|
||||
data |= panel->hdr_data.length << 8;
|
||||
data = version;
|
||||
data |= length << 8;
|
||||
data |= hdr->eotf << 16;
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_2 + mst_offset,
|
||||
data);
|
||||
@ -661,7 +685,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
|
||||
struct dp_catalog_private *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 header, parity, data, mst_offset = 0;
|
||||
u8 bpc, off = 0;
|
||||
u8 off = 0;
|
||||
u8 buf[SZ_128];
|
||||
|
||||
if (!panel) {
|
||||
@ -681,7 +705,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
|
||||
io_data = catalog->io.dp_link;
|
||||
|
||||
/* HEADER BYTE 1 */
|
||||
header = panel->hdr_data.vsc_header_byte1;
|
||||
header = panel->vsc_colorimetry.header.HB1;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_1_BIT)
|
||||
| (parity << PARITY_BYTE_1_BIT));
|
||||
@ -691,7 +715,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
|
||||
off += sizeof(data);
|
||||
|
||||
/* HEADER BYTE 2 */
|
||||
header = panel->hdr_data.vsc_header_byte2;
|
||||
header = panel->vsc_colorimetry.header.HB2;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_2_BIT)
|
||||
| (parity << PARITY_BYTE_2_BIT));
|
||||
@ -699,7 +723,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
|
||||
data);
|
||||
|
||||
/* HEADER BYTE 3 */
|
||||
header = panel->hdr_data.vsc_header_byte3;
|
||||
header = panel->vsc_colorimetry.header.HB3;
|
||||
parity = dp_header_get_parity(header);
|
||||
data = ((header << HEADER_BYTE_3_BIT)
|
||||
| (parity << PARITY_BYTE_3_BIT));
|
||||
@ -731,24 +755,9 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
|
||||
memcpy(buf + off, &data, sizeof(data));
|
||||
off += sizeof(data);
|
||||
|
||||
switch (panel->hdr_data.bpc) {
|
||||
default:
|
||||
case 10:
|
||||
bpc = BIT(1);
|
||||
break;
|
||||
case 8:
|
||||
bpc = BIT(0);
|
||||
break;
|
||||
case 6:
|
||||
bpc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
data = (panel->hdr_data.colorimetry & 0xF) |
|
||||
((panel->hdr_data.pixel_encoding & 0xF) << 4) |
|
||||
(bpc << 8) |
|
||||
((panel->hdr_data.dynamic_range & 0x1) << 15) |
|
||||
((panel->hdr_data.content_type & 0x7) << 16);
|
||||
data = (panel->vsc_colorimetry.data[16] & 0xFF) |
|
||||
((panel->vsc_colorimetry.data[17] & 0xFF) << 8) |
|
||||
((panel->vsc_colorimetry.data[18] & 0x7) << 16);
|
||||
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset,
|
||||
data);
|
||||
@ -775,15 +784,125 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
|
||||
DUMP_PREFIX_NONE, 16, 4, buf, off, false);
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_config_sdp(struct dp_catalog_panel *panel,
|
||||
bool en)
|
||||
{
|
||||
struct dp_catalog_private *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 cfg, cfg2;
|
||||
u32 sdp_cfg_off = 0;
|
||||
u32 sdp_cfg2_off = 0;
|
||||
|
||||
if (panel->stream_id >= DP_STREAM_MAX) {
|
||||
DP_ERR("invalid stream_id:%d\n", panel->stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv(panel);
|
||||
io_data = catalog->io.dp_link;
|
||||
|
||||
if (panel->stream_id == DP_STREAM_1) {
|
||||
sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG;
|
||||
sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2;
|
||||
}
|
||||
|
||||
cfg = dp_read(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG + sdp_cfg_off);
|
||||
cfg2 = dp_read(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG2 + sdp_cfg2_off);
|
||||
|
||||
if (en) {
|
||||
/* GEN0_SDP_EN */
|
||||
cfg |= BIT(17);
|
||||
dp_write(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
|
||||
|
||||
/* GENERIC0_SDPSIZE */
|
||||
cfg2 |= BIT(16);
|
||||
dp_write(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
|
||||
|
||||
/* setup the GENERIC0 in case of en = true */
|
||||
dp_catalog_panel_setup_vsc_sdp(panel);
|
||||
|
||||
} else {
|
||||
/* GEN0_SDP_EN */
|
||||
cfg &= ~BIT(17);
|
||||
dp_write(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
|
||||
|
||||
/* GENERIC0_SDPSIZE */
|
||||
cfg2 &= ~BIT(16);
|
||||
dp_write(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
|
||||
}
|
||||
|
||||
dp_catalog_panel_sdp_update(panel);
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel)
|
||||
{
|
||||
struct dp_catalog_private *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 reg_offset = 0;
|
||||
|
||||
if (!panel) {
|
||||
pr_err("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (panel->stream_id >= DP_STREAM_MAX) {
|
||||
pr_err("invalid stream_id:%d\n", panel->stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv(panel);
|
||||
io_data = catalog->io.dp_link;
|
||||
|
||||
if (panel->stream_id == DP_STREAM_1)
|
||||
reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0;
|
||||
|
||||
DP_DEBUG("misc settings = 0x%x\n", panel->misc_val);
|
||||
dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset,
|
||||
panel->misc_val);
|
||||
}
|
||||
|
||||
static int dp_catalog_panel_set_colorspace(struct dp_catalog_panel *panel,
|
||||
bool vsc_supported)
|
||||
{
|
||||
struct dp_catalog_private *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
|
||||
if (!panel) {
|
||||
pr_err("invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (panel->stream_id >= DP_STREAM_MAX) {
|
||||
pr_err("invalid stream_id:%d\n", panel->stream_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv(panel);
|
||||
io_data = catalog->io.dp_link;
|
||||
|
||||
if (vsc_supported) {
|
||||
dp_catalog_panel_setup_vsc_sdp(panel);
|
||||
dp_catalog_panel_sdp_update(panel);
|
||||
} else
|
||||
dp_catalog_panel_config_misc(panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
|
||||
u32 dhdr_max_pkts)
|
||||
u32 dhdr_max_pkts, bool flush)
|
||||
{
|
||||
struct dp_catalog_private *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
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;
|
||||
|
||||
@ -803,7 +922,6 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
|
||||
if (panel->stream_id == DP_STREAM_1) {
|
||||
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;
|
||||
}
|
||||
@ -826,34 +944,30 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
|
||||
dp_catalog_panel_setup_vsif_infoframe_sdp(panel);
|
||||
}
|
||||
|
||||
/* GEN0_SDP_EN, GEN2_SDP_EN */
|
||||
cfg |= BIT(17) | BIT(19);
|
||||
/* GEN2_SDP_EN */
|
||||
cfg |= BIT(19);
|
||||
dp_write(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
|
||||
|
||||
/* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */
|
||||
cfg2 |= BIT(16) | BIT(20);
|
||||
/* GENERIC2_SDPSIZE */
|
||||
cfg2 |= BIT(20);
|
||||
dp_write(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
|
||||
|
||||
dp_catalog_panel_setup_vsc_sdp(panel);
|
||||
dp_catalog_panel_setup_hdr_infoframe_sdp(panel);
|
||||
|
||||
/* indicates presence of VSC (BIT(6) of MISC1) */
|
||||
misc |= BIT(14);
|
||||
|
||||
if (panel->hdr_data.hdr_meta.eotf)
|
||||
if (panel->hdr_meta.eotf)
|
||||
DP_DEBUG("Enabled\n");
|
||||
else
|
||||
DP_DEBUG("Reset\n");
|
||||
} else {
|
||||
/* VSCEXT_SDP_EN, GEN0_SDP_EN */
|
||||
cfg &= ~BIT(16) & ~BIT(17) & ~BIT(19);
|
||||
/* VSCEXT_SDP_ENG */
|
||||
cfg &= ~BIT(16) & ~BIT(19);
|
||||
dp_write(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
|
||||
|
||||
/* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */
|
||||
cfg2 &= ~BIT(16) & ~BIT(20);
|
||||
cfg2 &= ~BIT(20);
|
||||
dp_write(catalog->exe_mode, io_data,
|
||||
MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
|
||||
|
||||
@ -862,19 +976,13 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4
|
||||
+ sdp_cfg4_off, cfg4);
|
||||
|
||||
/* switch back to MSA */
|
||||
misc &= ~BIT(14);
|
||||
|
||||
DP_DEBUG("Disabled\n");
|
||||
}
|
||||
|
||||
dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + misc1_misc0_off,
|
||||
misc);
|
||||
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
|
||||
0x01);
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
|
||||
0x00);
|
||||
if (flush) {
|
||||
DP_DEBUG("flushing HDR metadata\n");
|
||||
dp_catalog_panel_sdp_update(panel);
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_update_transfer_unit(
|
||||
@ -1109,33 +1217,6 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl,
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel)
|
||||
{
|
||||
struct dp_catalog_private *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 reg_offset = 0;
|
||||
|
||||
if (!panel) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (panel->stream_id >= DP_STREAM_MAX) {
|
||||
DP_ERR("invalid stream_id:%d\n", panel->stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv(panel);
|
||||
io_data = catalog->io.dp_link;
|
||||
|
||||
if (panel->stream_id == DP_STREAM_1)
|
||||
reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0;
|
||||
|
||||
DP_DEBUG("misc settings = 0x%x\n", panel->misc_val);
|
||||
dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset,
|
||||
panel->misc_val);
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel,
|
||||
u32 rate, u32 stream_rate_khz)
|
||||
{
|
||||
@ -2494,7 +2575,6 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel)
|
||||
u32 offset = 0;
|
||||
u32 sdp_cfg_off = 0;
|
||||
u32 sdp_cfg2_off = 0;
|
||||
u32 sdp_cfg3_off = 0;
|
||||
|
||||
/*
|
||||
* Source Device Information
|
||||
@ -2567,7 +2647,6 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel)
|
||||
if (panel->stream_id == DP_STREAM_1) {
|
||||
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;
|
||||
}
|
||||
|
||||
spd_cfg = dp_read(catalog->exe_mode, io_data,
|
||||
@ -2584,10 +2663,7 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel)
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off,
|
||||
spd_cfg2);
|
||||
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
|
||||
0x1);
|
||||
dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
|
||||
0x0);
|
||||
dp_catalog_panel_sdp_update(panel);
|
||||
}
|
||||
|
||||
static void dp_catalog_get_io_buf(struct dp_catalog_private *catalog)
|
||||
@ -2745,9 +2821,11 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
|
||||
struct dp_catalog_panel panel = {
|
||||
.timing_cfg = dp_catalog_panel_timing_cfg,
|
||||
.config_hdr = dp_catalog_panel_config_hdr,
|
||||
.config_sdp = dp_catalog_panel_config_sdp,
|
||||
.tpg_config = dp_catalog_panel_tpg_cfg,
|
||||
.config_spd = dp_catalog_panel_config_spd,
|
||||
.config_misc = dp_catalog_panel_config_misc,
|
||||
.set_colorspace = dp_catalog_panel_set_colorspace,
|
||||
.config_msa = dp_catalog_panel_config_msa,
|
||||
.update_transfer_unit = dp_catalog_panel_update_transfer_unit,
|
||||
.config_ctrl = dp_catalog_panel_config_ctrl,
|
||||
|
@ -6,6 +6,7 @@
|
||||
#ifndef _DP_CATALOG_H_
|
||||
#define _DP_CATALOG_H_
|
||||
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/msm_drm.h>
|
||||
|
||||
#include "dp_parser.h"
|
||||
@ -39,32 +40,9 @@ enum dp_stream_id {
|
||||
DP_STREAM_MAX,
|
||||
};
|
||||
|
||||
struct dp_catalog_hdr_data {
|
||||
u32 vsc_header_byte0;
|
||||
u32 vsc_header_byte1;
|
||||
u32 vsc_header_byte2;
|
||||
u32 vsc_header_byte3;
|
||||
|
||||
u32 vscext_header_byte0;
|
||||
u32 vscext_header_byte1;
|
||||
u32 vscext_header_byte2;
|
||||
u32 vscext_header_byte3;
|
||||
|
||||
u32 shdr_header_byte0;
|
||||
u32 shdr_header_byte1;
|
||||
u32 shdr_header_byte2;
|
||||
u32 shdr_header_byte3;
|
||||
|
||||
u32 bpc;
|
||||
|
||||
u32 version;
|
||||
u32 length;
|
||||
u32 pixel_encoding;
|
||||
u32 colorimetry;
|
||||
u32 dynamic_range;
|
||||
u32 content_type;
|
||||
|
||||
struct drm_msm_ext_hdr_metadata hdr_meta;
|
||||
struct dp_catalog_vsc_sdp_colorimetry {
|
||||
struct dp_sdp_header header;
|
||||
u8 data[32];
|
||||
};
|
||||
|
||||
struct dp_catalog_aux {
|
||||
@ -197,7 +175,10 @@ struct dp_catalog_panel {
|
||||
u8 *spd_vendor_name;
|
||||
u8 *spd_product_description;
|
||||
|
||||
struct dp_catalog_hdr_data hdr_data;
|
||||
struct dp_catalog_vsc_sdp_colorimetry vsc_colorimetry;
|
||||
struct dp_sdp_header dhdr_vsif_sdp;
|
||||
struct dp_sdp_header shdr_if_sdp;
|
||||
struct drm_msm_ext_hdr_metadata hdr_meta;
|
||||
|
||||
/* TPG */
|
||||
u32 hsync_period;
|
||||
@ -222,7 +203,10 @@ struct dp_catalog_panel {
|
||||
|
||||
int (*timing_cfg)(struct dp_catalog_panel *panel);
|
||||
void (*config_hdr)(struct dp_catalog_panel *panel, bool en,
|
||||
u32 dhdr_max_pkts);
|
||||
u32 dhdr_max_pkts, bool flush);
|
||||
void (*config_sdp)(struct dp_catalog_panel *panel, bool en);
|
||||
int (*set_colorspace)(struct dp_catalog_panel *panel,
|
||||
bool vsc_supported);
|
||||
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);
|
||||
|
@ -1627,7 +1627,7 @@ static void dp_display_stream_post_enable(struct dp_display_private *dp,
|
||||
struct dp_panel *dp_panel)
|
||||
{
|
||||
dp_panel->spd_config(dp_panel);
|
||||
dp_panel->setup_hdr(dp_panel, NULL, false, 0);
|
||||
dp_panel->setup_hdr(dp_panel, NULL, false, 0, true);
|
||||
}
|
||||
|
||||
static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
|
||||
@ -1676,6 +1676,14 @@ end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dp_display_clear_colorspaces(struct dp_display *dp_display)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
||||
connector = dp_display->base_connector;
|
||||
connector->color_enc_fmt = 0;
|
||||
}
|
||||
|
||||
static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
|
||||
{
|
||||
struct dp_display_private *dp;
|
||||
@ -1732,6 +1740,8 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
|
||||
}
|
||||
}
|
||||
|
||||
dp_display_clear_colorspaces(dp_display);
|
||||
|
||||
clean:
|
||||
if (dp_panel->audio_supported)
|
||||
dp_panel->audio->off(dp_panel->audio);
|
||||
@ -2082,8 +2092,10 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
|
||||
struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update)
|
||||
{
|
||||
struct dp_panel *dp_panel;
|
||||
struct sde_connector *sde_conn;
|
||||
struct dp_display_private *dp;
|
||||
u64 core_clk_rate;
|
||||
bool flush_hdr;
|
||||
|
||||
if (!dp_display || !panel) {
|
||||
DP_ERR("invalid input\n");
|
||||
@ -2092,6 +2104,7 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
|
||||
|
||||
dp_panel = panel;
|
||||
dp = container_of(dp_display, struct dp_display_private, dp_display);
|
||||
sde_conn = to_sde_connector(dp_panel->connector);
|
||||
|
||||
core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk");
|
||||
if (!core_clk_rate) {
|
||||
@ -2099,7 +2112,36 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update, core_clk_rate);
|
||||
/*
|
||||
* In rare cases where HDR metadata is updated independently
|
||||
* flush the HDR metadata immediately instead of relying on
|
||||
* the colorspace
|
||||
*/
|
||||
flush_hdr = !sde_conn->colorspace_updated;
|
||||
|
||||
if (flush_hdr)
|
||||
DP_DEBUG("flushing the HDR metadata\n");
|
||||
else
|
||||
DP_DEBUG("piggy-backing with colorspace\n");
|
||||
|
||||
return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update,
|
||||
core_clk_rate, flush_hdr);
|
||||
}
|
||||
|
||||
static int dp_display_setup_colospace(struct dp_display *dp_display,
|
||||
void *panel,
|
||||
u32 colorspace)
|
||||
{
|
||||
struct dp_panel *dp_panel;
|
||||
|
||||
if (!dp_display || !panel) {
|
||||
pr_err("invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dp_panel = panel;
|
||||
|
||||
return dp_panel->set_colorspace(dp_panel, colorspace);
|
||||
}
|
||||
|
||||
static int dp_display_create_workqueue(struct dp_display_private *dp)
|
||||
@ -2623,6 +2665,7 @@ static int dp_display_probe(struct platform_device *pdev)
|
||||
dp_display_mst_get_fixed_topology_port;
|
||||
g_dp_display->wakeup_phy_layer =
|
||||
dp_display_wakeup_phy_layer;
|
||||
g_dp_display->set_colorspace = dp_display_setup_colospace;
|
||||
|
||||
rc = component_add(&pdev->dev, &dp_display_comp_ops);
|
||||
if (rc) {
|
||||
|
@ -93,6 +93,8 @@ struct dp_display {
|
||||
int (*config_hdr)(struct dp_display *dp_display, void *panel,
|
||||
struct drm_msm_ext_hdr_metadata *hdr_meta,
|
||||
bool dhdr_update);
|
||||
int (*set_colorspace)(struct dp_display *dp_display, void *panel,
|
||||
u32 colorspace);
|
||||
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);
|
||||
|
@ -326,6 +326,25 @@ int dp_connector_config_hdr(struct drm_connector *connector, void *display,
|
||||
c_state->dyn_hdr_meta.dynamic_hdr_update);
|
||||
}
|
||||
|
||||
int dp_connector_set_colorspace(struct drm_connector *connector,
|
||||
void *display)
|
||||
{
|
||||
struct dp_display *dp_display = display;
|
||||
struct sde_connector *sde_conn;
|
||||
|
||||
if (!dp_display || !connector)
|
||||
return -EINVAL;
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
if (!sde_conn->drv_panel) {
|
||||
pr_err("invalid dp panel\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dp_display->set_colorspace(dp_display,
|
||||
sde_conn->drv_panel, connector->state->colorspace);
|
||||
}
|
||||
|
||||
int dp_connector_post_init(struct drm_connector *connector, void *display)
|
||||
{
|
||||
int rc;
|
||||
@ -469,6 +488,32 @@ void dp_connector_post_open(struct drm_connector *connector, void *display)
|
||||
dp->post_open(dp);
|
||||
}
|
||||
|
||||
int dp_connector_atomic_check(struct drm_connector *connector,
|
||||
void *display,
|
||||
struct drm_connector_state *c_state)
|
||||
{
|
||||
struct sde_connector *sde_conn;
|
||||
struct drm_connector_state *old_state =
|
||||
drm_atomic_get_old_connector_state(c_state->state, connector);
|
||||
|
||||
if (!connector || !display)
|
||||
return -EINVAL;
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
|
||||
/*
|
||||
* Marking the colorspace has been changed
|
||||
* the flag shall be checked in the pre_kickoff
|
||||
* to configure the new colorspace in HW
|
||||
*/
|
||||
if (c_state->colorspace != old_state->colorspace) {
|
||||
DP_DEBUG("colorspace has been updated\n");
|
||||
sde_conn->colorspace_updated = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dp_connector_get_modes(struct drm_connector *connector,
|
||||
void *display, const struct msm_resource_caps_info *avail_res)
|
||||
{
|
||||
|
@ -37,6 +37,27 @@ int dp_connector_config_hdr(struct drm_connector *connector,
|
||||
void *display,
|
||||
struct sde_connector_state *c_state);
|
||||
|
||||
/**
|
||||
* dp_connector_atomic_check - callback to perform atomic
|
||||
* check for DP
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display handle
|
||||
* @c_state: connect state data
|
||||
* Returns: Zero on success
|
||||
*/
|
||||
int dp_connector_atomic_check(struct drm_connector *connector,
|
||||
void *display,
|
||||
struct drm_connector_state *c_state);
|
||||
|
||||
/**
|
||||
* dp_connector_set_colorspace - callback to set new colorspace
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display handle
|
||||
* Returns: Zero on success
|
||||
*/
|
||||
int dp_connector_set_colorspace(struct drm_connector *connector,
|
||||
void *display);
|
||||
|
||||
/**
|
||||
* dp_connector_post_init - callback to perform additional initialization steps
|
||||
* @connector: Pointer to drm connector structure
|
||||
|
@ -1352,7 +1352,7 @@ static int dp_link_get_colorimetry_config(struct dp_link *dp_link)
|
||||
/* Only RGB_VESA nd RGB_CEA supported for now */
|
||||
switch (dr) {
|
||||
case DP_DYNAMIC_RANGE_RGB_CEA:
|
||||
cc = BIT(3);
|
||||
cc = BIT(2);
|
||||
break;
|
||||
case DP_DYNAMIC_RANGE_RGB_VESA:
|
||||
default:
|
||||
|
@ -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;
|
||||
|
@ -150,7 +150,9 @@ struct dp_panel {
|
||||
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,
|
||||
bool dhdr_update, u64 core_clk_rate);
|
||||
bool dhdr_update, u64 core_clk_rate, bool flush);
|
||||
int (*set_colorspace)(struct dp_panel *dp_panel,
|
||||
u32 colorspace);
|
||||
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);
|
||||
|
@ -190,6 +190,7 @@ enum msm_mdp_conn_property {
|
||||
CONNECTOR_PROP_ROI_V1,
|
||||
CONNECTOR_PROP_BL_SCALE,
|
||||
CONNECTOR_PROP_SV_BL_SCALE,
|
||||
CONNECTOR_PROP_SUPPORTED_COLORSPACES,
|
||||
|
||||
/* enum/bitmask properties */
|
||||
CONNECTOR_PROP_TOPOLOGY_NAME,
|
||||
|
@ -606,6 +606,19 @@ static int _sde_connector_update_bl_scale(struct sde_connector *c_conn)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void sde_connector_set_colorspace(struct sde_connector *c_conn)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (c_conn->ops.set_colorspace)
|
||||
rc = c_conn->ops.set_colorspace(&c_conn->base,
|
||||
c_conn->display);
|
||||
|
||||
if (rc)
|
||||
SDE_ERROR_CONN(c_conn, "cannot apply new colorspace %d\n", rc);
|
||||
|
||||
}
|
||||
|
||||
void sde_connector_set_qsync_params(struct drm_connector *connector)
|
||||
{
|
||||
struct sde_connector *c_conn = to_sde_connector(connector);
|
||||
@ -680,6 +693,12 @@ static int _sde_connector_update_dirty_properties(
|
||||
}
|
||||
}
|
||||
|
||||
/* if colorspace needs to be updated do it first */
|
||||
if (c_conn->colorspace_updated) {
|
||||
c_conn->colorspace_updated = false;
|
||||
sde_connector_set_colorspace(c_conn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special handling for postproc properties and
|
||||
* for updating backlight if any unset backlight level is present
|
||||
@ -1480,6 +1499,20 @@ static void sde_connector_update_hdr_props(struct drm_connector *connector)
|
||||
&hdr, sizeof(hdr), CONNECTOR_PROP_EXT_HDR_INFO);
|
||||
}
|
||||
|
||||
static void sde_connector_update_colorspace(struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = msm_property_set_property(
|
||||
sde_connector_get_propinfo(connector),
|
||||
sde_connector_get_property_state(connector->state),
|
||||
CONNECTOR_PROP_SUPPORTED_COLORSPACES,
|
||||
connector->color_enc_fmt);
|
||||
|
||||
if (ret)
|
||||
SDE_ERROR("failed to set colorspace property for connector\n");
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
sde_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
@ -1920,6 +1953,9 @@ static int sde_connector_get_modes(struct drm_connector *connector)
|
||||
if (c_conn->hdr_capable)
|
||||
sde_connector_update_hdr_props(connector);
|
||||
|
||||
if (c_conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort)
|
||||
sde_connector_update_colorspace(connector);
|
||||
|
||||
return mode_count;
|
||||
}
|
||||
|
||||
@ -2118,6 +2154,7 @@ static const struct drm_connector_helper_funcs sde_connector_helper_ops = {
|
||||
.get_modes = sde_connector_get_modes,
|
||||
.mode_valid = sde_connector_mode_valid,
|
||||
.best_encoder = sde_connector_best_encoder,
|
||||
.atomic_check = sde_connector_atomic_check,
|
||||
};
|
||||
|
||||
static const struct drm_connector_helper_funcs sde_connector_helper_ops_v2 = {
|
||||
@ -2295,6 +2332,7 @@ static int _sde_connector_install_properties(struct drm_device *dev,
|
||||
{
|
||||
struct dsi_display *dsi_display;
|
||||
int rc;
|
||||
struct drm_connector *connector;
|
||||
|
||||
msm_property_install_blob(&c_conn->property_info, "capabilities",
|
||||
DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_SDE_INFO);
|
||||
@ -2307,6 +2345,8 @@ static int _sde_connector_install_properties(struct drm_device *dev,
|
||||
return rc;
|
||||
}
|
||||
|
||||
connector = &c_conn->base;
|
||||
|
||||
msm_property_install_blob(&c_conn->property_info, "mode_properties",
|
||||
DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_MODE_INFO);
|
||||
|
||||
@ -2350,6 +2390,11 @@ static int _sde_connector_install_properties(struct drm_device *dev,
|
||||
&hdr,
|
||||
sizeof(hdr),
|
||||
CONNECTOR_PROP_EXT_HDR_INFO);
|
||||
|
||||
/* create and attach colorspace property for DP */
|
||||
if (!drm_mode_create_colorspace_property(connector))
|
||||
drm_object_attach_property(&connector->base,
|
||||
connector->colorspace_property, 0);
|
||||
}
|
||||
|
||||
msm_property_install_volatile_range(&c_conn->property_info,
|
||||
@ -2389,6 +2434,12 @@ static int _sde_connector_install_properties(struct drm_device *dev,
|
||||
c_conn->bl_scale = MAX_BL_SCALE_LEVEL;
|
||||
c_conn->bl_scale_sv = MAX_SV_BL_SCALE_LEVEL;
|
||||
|
||||
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort)
|
||||
msm_property_install_range(&c_conn->property_info,
|
||||
"supported_colorspaces",
|
||||
DRM_MODE_PROP_IMMUTABLE, 0, 0xffff, 0,
|
||||
CONNECTOR_PROP_SUPPORTED_COLORSPACES);
|
||||
|
||||
/* enum/bitmask properties */
|
||||
msm_property_install_enum(&c_conn->property_info, "topology_name",
|
||||
DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name,
|
||||
|
@ -168,6 +168,14 @@ struct sde_connector_ops {
|
||||
int (*set_backlight)(struct drm_connector *connector,
|
||||
void *display, u32 bl_lvl);
|
||||
|
||||
/**
|
||||
* set_colorspace - set colorspace for connector
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display structure
|
||||
*/
|
||||
int (*set_colorspace)(struct drm_connector *connector,
|
||||
void *display);
|
||||
|
||||
/**
|
||||
* soft_reset - perform a soft reset on the connector
|
||||
* @display: Pointer to private display structure
|
||||
@ -400,6 +408,7 @@ struct sde_connector_dyn_hdr_metadata {
|
||||
* @allow_bl_update: Flag to indicate if BL update is allowed currently or not
|
||||
* @qsync_mode: Cached Qsync mode, 0=disabled, 1=continuous mode
|
||||
* @qsync_updated: Qsync settings were updated
|
||||
* @colorspace_updated: Colorspace property was updated
|
||||
* last_cmd_tx_sts: status of the last command transfer
|
||||
* @hdr_capable: external hdr support present
|
||||
* @core_clk_rate: MDP core clk rate used for dynamic HDR packet calculation
|
||||
@ -452,6 +461,8 @@ struct sde_connector {
|
||||
u32 qsync_mode;
|
||||
bool qsync_updated;
|
||||
|
||||
bool colorspace_updated;
|
||||
|
||||
bool last_cmd_tx_sts;
|
||||
bool hdr_capable;
|
||||
};
|
||||
|
@ -1222,11 +1222,13 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
|
||||
.post_init = dp_connector_post_init,
|
||||
.detect = dp_connector_detect,
|
||||
.get_modes = dp_connector_get_modes,
|
||||
.atomic_check = dp_connector_atomic_check,
|
||||
.mode_valid = dp_connector_mode_valid,
|
||||
.get_info = dp_connector_get_info,
|
||||
.get_mode_info = dp_connector_get_mode_info,
|
||||
.post_open = dp_connector_post_open,
|
||||
.check_status = NULL,
|
||||
.set_colorspace = dp_connector_set_colorspace,
|
||||
.config_hdr = dp_connector_config_hdr,
|
||||
.cmd_transfer = NULL,
|
||||
.cont_splash_config = NULL,
|
||||
|
Loading…
Reference in New Issue
Block a user