drm/rockchip: drv: Parse edid next hdr info in rockchip driver

To be compatible with GKI, we parse the edid next hdr information
in rockchup-drm driver.

Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
Change-Id: Id6fd8f2d8429b07472c6562c223ae84262952e8d
This commit is contained in:
Algea Cao
2021-10-29 15:29:44 +08:00
committed by Tao Huang
parent 60d1c80f6b
commit 31d7cfd41e
2 changed files with 271 additions and 0 deletions

View File

@@ -267,6 +267,23 @@ cea_db_payload_len(const u8 *db)
(i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); \
(i) += cea_db_payload_len(&(cea)[(i)]) + 1)
#define HDMI_NEXT_HDR_VSDB_OUI 0xd04601
static bool cea_db_is_hdmi_next_hdr_block(const u8 *db)
{
unsigned int oui;
if (cea_db_tag(db) != 0x07)
return false;
if (cea_db_payload_len(db) < 11)
return false;
oui = db[3] << 16 | db[2] << 8 | db[1];
return oui == HDMI_NEXT_HDR_VSDB_OUI;
}
static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
{
unsigned int oui;
@@ -578,6 +595,152 @@ void parse_edid_forum_vsdb(struct rockchip_drm_dsc_cap *dsc_cap,
}
}
enum {
VER_26_BYTE_V0,
VER_15_BYTE_V1,
VER_12_BYTE_V1,
VER_12_BYTE_V2,
};
static int check_next_hdr_version(const u8 *next_hdr_db)
{
u16 ver;
ver = (next_hdr_db[5] & 0xf0) << 8 | next_hdr_db[0];
switch (ver) {
case 0x00f9:
return VER_26_BYTE_V0;
case 0x20ee:
return VER_15_BYTE_V1;
case 0x20eb:
return VER_12_BYTE_V1;
case 0x40eb:
return VER_12_BYTE_V2;
default:
return -ENOENT;
}
}
static void parse_ver_26_v0_data(struct ver_26_v0 *hdr, const u8 *data)
{
hdr->yuv422_12bit = data[5] & BIT(0);
hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1;
hdr->global_dimming = (data[5] & BIT(2)) >> 2;
hdr->dm_major_ver = (data[21] & 0xf0) >> 4;
hdr->dm_minor_ver = data[21] & 0xf;
hdr->t_min_pq = (data[19] << 4) | ((data[18] & 0xf0) >> 4);
hdr->t_max_pq = (data[20] << 4) | (data[18] & 0xf);
hdr->rx = (data[7] << 4) | ((data[6] & 0xf0) >> 4);
hdr->ry = (data[8] << 4) | (data[6] & 0xf);
hdr->gx = (data[10] << 4) | ((data[9] & 0xf0) >> 4);
hdr->gy = (data[11] << 4) | (data[9] & 0xf);
hdr->bx = (data[13] << 4) | ((data[12] & 0xf0) >> 4);
hdr->by = (data[14] << 4) | (data[12] & 0xf);
hdr->wx = (data[16] << 4) | ((data[15] & 0xf0) >> 4);
hdr->wy = (data[17] << 4) | (data[15] & 0xf);
}
static void parse_ver_15_v1_data(struct ver_15_v1 *hdr, const u8 *data)
{
hdr->yuv422_12bit = data[5] & BIT(0);
hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1;
hdr->global_dimming = data[6] & BIT(0);
hdr->dm_version = (data[5] & 0x1c) >> 2;
hdr->colorimetry = data[7] & BIT(0);
hdr->t_max_lum = (data[6] & 0xfe) >> 1;
hdr->t_min_lum = (data[7] & 0xfe) >> 1;
hdr->rx = data[9];
hdr->ry = data[10];
hdr->gx = data[11];
hdr->gy = data[12];
hdr->bx = data[13];
hdr->by = data[14];
}
static void parse_ver_12_v1_data(struct ver_12_v1 *hdr, const u8 *data)
{
hdr->yuv422_12bit = data[5] & BIT(0);
hdr->support_2160p_60 = (data[5] & BIT(1)) >> 1;
hdr->global_dimming = data[6] & BIT(0);
hdr->dm_version = (data[5] & 0x1c) >> 2;
hdr->colorimetry = data[7] & BIT(0);
hdr->t_max_lum = (data[6] & 0xfe) >> 1;
hdr->t_min_lum = (data[7] & 0xfe) >> 1;
hdr->low_latency = data[8] & 0x3;
hdr->unique_rx = (data[11] & 0xf8) >> 3;
hdr->unique_ry = (data[11] & 0x7) << 2 | (data[10] & BIT(0)) << 1 |
(data[9] & BIT(0));
hdr->unique_gx = (data[9] & 0xfe) >> 1;
hdr->unique_gy = (data[10] & 0xfe) >> 1;
hdr->unique_bx = (data[8] & 0xe0) >> 5;
hdr->unique_by = (data[8] & 0x1c) >> 2;
}
static void parse_ver_12_v2_data(struct ver_12_v2 *hdr, const u8 *data)
{
hdr->yuv422_12bit = data[5] & BIT(0);
hdr->backlt_ctrl = (data[5] & BIT(1)) >> 1;
hdr->global_dimming = (data[6] & BIT(2)) >> 2;
hdr->dm_version = (data[5] & 0x1c) >> 2;
hdr->backlt_min_luma = data[6] & 0x3;
hdr->interface = data[7] & 0x3;
hdr->yuv444_10b_12b = (data[8] & BIT(0)) << 1 | (data[9] & BIT(0));
hdr->t_min_pq_v2 = (data[6] & 0xf8) >> 3;
hdr->t_max_pq_v2 = (data[7] & 0xf8) >> 3;
hdr->unique_rx = (data[10] & 0xf8) >> 3;
hdr->unique_ry = (data[11] & 0xf8) >> 3;
hdr->unique_gx = (data[8] & 0xfe) >> 1;
hdr->unique_gy = (data[9] & 0xfe) >> 1;
hdr->unique_bx = data[10] & 0x7;
hdr->unique_by = data[11] & 0x7;
}
static
void parse_next_hdr_block(struct next_hdr_sink_data *sink_data,
const u8 *next_hdr_db)
{
int version;
version = check_next_hdr_version(next_hdr_db);
if (version < 0)
return;
sink_data->version = version;
switch (version) {
case VER_26_BYTE_V0:
parse_ver_26_v0_data(&sink_data->ver_26_v0, next_hdr_db);
break;
case VER_15_BYTE_V1:
parse_ver_15_v1_data(&sink_data->ver_15_v1, next_hdr_db);
break;
case VER_12_BYTE_V1:
parse_ver_12_v1_data(&sink_data->ver_12_v1, next_hdr_db);
break;
case VER_12_BYTE_V2:
parse_ver_12_v2_data(&sink_data->ver_12_v2, next_hdr_db);
break;
default:
break;
}
}
int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap,
u8 *max_frl_rate_per_lane, u8 *max_lanes,
const struct edid *edid)
@@ -607,6 +770,35 @@ int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap,
}
EXPORT_SYMBOL(rockchip_drm_parse_cea_ext);
int rockchip_drm_parse_next_hdr(struct next_hdr_sink_data *sink_data,
const struct edid *edid)
{
const u8 *edid_ext;
int i, start, end;
if (!sink_data || !edid)
return -EINVAL;
memset(sink_data, 0, sizeof(struct next_hdr_sink_data));
edid_ext = find_cea_extension(edid);
if (!edid_ext)
return -EINVAL;
if (cea_db_offsets(edid_ext, &start, &end))
return -EINVAL;
for_each_cea_db(edid_ext, i, start, end) {
const u8 *db = &edid_ext[i];
if (cea_db_is_hdmi_next_hdr_block(db))
parse_next_hdr_block(sink_data, db);
}
return 0;
}
EXPORT_SYMBOL(rockchip_drm_parse_next_hdr);
/*
* Attach a (component) device to the shared drm dma mapping from master drm
* device. This is used by the VOPs to map GEM buffers to a common DMA

View File

@@ -221,6 +221,83 @@ struct rockchip_drm_dsc_cap {
int clk_per_slice;
};
struct ver_26_v0 {
u8 yuv422_12bit;
u8 support_2160p_60;
u8 global_dimming;
u8 dm_major_ver;
u8 dm_minor_ver;
u16 t_min_pq;
u16 t_max_pq;
u16 rx;
u16 ry;
u16 gx;
u16 gy;
u16 bx;
u16 by;
u16 wx;
u16 wy;
} __packed;
struct ver_15_v1 {
u8 yuv422_12bit;
u8 support_2160p_60;
u8 global_dimming;
u8 dm_version;
u8 colorimetry;
u8 t_max_lum;
u8 t_min_lum;
u8 rx;
u8 ry;
u8 gx;
u8 gy;
u8 bx;
u8 by;
} __packed;
struct ver_12_v1 {
u8 yuv422_12bit;
u8 support_2160p_60;
u8 global_dimming;
u8 dm_version;
u8 colorimetry;
u8 low_latency;
u8 t_max_lum;
u8 t_min_lum;
u8 unique_rx;
u8 unique_ry;
u8 unique_gx;
u8 unique_gy;
u8 unique_bx;
u8 unique_by;
} __packed;
struct ver_12_v2 {
u8 yuv422_12bit;
u8 backlt_ctrl;
u8 global_dimming;
u8 dm_version;
u8 backlt_min_luma;
u8 interface;
u8 yuv444_10b_12b;
u8 t_min_pq_v2;
u8 t_max_pq_v2;
u8 unique_rx;
u8 unique_ry;
u8 unique_gx;
u8 unique_gy;
u8 unique_bx;
u8 unique_by;
} __packed;
struct next_hdr_sink_data {
u8 version;
struct ver_26_v0 ver_26_v0;
struct ver_15_v1 ver_15_v1;
struct ver_12_v1 ver_12_v1;
struct ver_12_v2 ver_12_v2;
} __packed;
/*
* Rockchip drm private crtc funcs.
* @loader_protect: protect loader logo crtc's power
@@ -341,6 +418,8 @@ int rockchip_drm_get_yuv422_format(struct drm_connector *connector,
int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap,
u8 *max_frl_rate_per_lane, u8 *max_lanes,
const struct edid *edid);
int rockchip_drm_parse_next_hdr(struct next_hdr_sink_data *sink_data,
const struct edid *edid);
extern struct platform_driver cdn_dp_driver;
extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;