hdmitx: add dynamic hdr info to vpp

PD#171350: hdmitx: add dynamic hdr info to vpp

cat /sys/class/amhdmitx/amhdmitx/hdr_cap
cat /sys/class/display/vinfo

Change-Id: I0d42c33e33ccc1f8d56545df25efc2cc60e08f58
Signed-off-by: Yi Zhou <yi.zhou@amlogic.com>
This commit is contained in:
Yi Zhou
2018-08-08 16:45:26 +08:00
committed by Jianxin Pan
parent 3367113918
commit 2a2a5305a7
6 changed files with 260 additions and 66 deletions

View File

@@ -58,7 +58,12 @@
#define EXTENSION_VENDOR_SPECIFIC 0x1
#define EXTENSION_COLORMETRY_TAG 0x5
/* DRM stands for "Dynamic Range and Mastering " */
#define EXTENSION_DRM_TAG 0x6
#define EXTENSION_DRM_STATIC_TAG 0x6
#define EXTENSION_DRM_DYNAMIC_TAG 0x7
#define TYPE_1_HDR_METADATA_TYPE 0x0001
#define TS_103_433_SPEC_TYPE 0x0002
#define ITU_T_H265_SPEC_TYPE 0x0003
#define TYPE_4_HDR_METADATA_TYPE 0x0004
/* Video Format Preference Data block */
#define EXTENSION_VFPDB_TAG 0xd
#define EXTENSION_Y420_VDB_TAG 0xe
@@ -943,7 +948,7 @@ INVALID_Y420VDB:
return -1;
}
static int Edid_ParsingDRMBlock(struct rx_cap *pRXCap,
static int Edid_ParsingDRMStaticBlock(struct rx_cap *pRXCap,
unsigned char *buf)
{
unsigned char tag = 0, ext_tag = 0, data_end = 0;
@@ -954,8 +959,8 @@ static int Edid_ParsingDRMBlock(struct rx_cap *pRXCap,
pos++;
ext_tag = buf[pos];
if ((tag != HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG)
|| (ext_tag != EXTENSION_DRM_TAG))
goto INVALID_DRM;
|| (ext_tag != EXTENSION_DRM_STATIC_TAG))
goto INVALID_DRM_STATIC;
pos++;
pRXCap->hdr_sup_eotf_sdr = !!(buf[pos] & (0x1 << 0));
pRXCap->hdr_sup_eotf_hdr = !!(buf[pos] & (0x1 << 1));
@@ -982,8 +987,66 @@ static int Edid_ParsingDRMBlock(struct rx_cap *pRXCap,
return 0;
}
return 0;
INVALID_DRM:
pr_info("[%s] it's not a valid DRM\n", __func__);
INVALID_DRM_STATIC:
pr_info("[%s] it's not a valid DRM STATIC BLOCK\n", __func__);
return -1;
}
static int Edid_ParsingDRMDynamicBlock(struct rx_cap *pRXCap,
unsigned char *buf)
{
unsigned char tag = 0, ext_tag = 0, data_end = 0;
unsigned int pos = 0;
unsigned int type;
unsigned int type_length;
unsigned int i;
unsigned int num;
tag = (buf[pos] >> 5) & 0x7;
data_end = (buf[pos] & 0x1f);
pos++;
ext_tag = buf[pos];
if ((tag != HDMI_EDID_BLOCK_TYPE_EXTENDED_TAG)
|| (ext_tag != EXTENSION_DRM_DYNAMIC_TAG))
goto INVALID_DRM_DYNAMIC;
pos++;
data_end--;/*extended tag code byte doesn't need*/
while (data_end) {
type_length = buf[pos];
pos++;
type = (buf[pos + 1] << 8) | buf[pos];
pos += 2;
switch (type) {
case TS_103_433_SPEC_TYPE:
num = 1;
break;
case ITU_T_H265_SPEC_TYPE:
num = 2;
break;
case TYPE_4_HDR_METADATA_TYPE:
num = 3;
break;
case TYPE_1_HDR_METADATA_TYPE:
default:
num = 0;
break;
}
pRXCap->hdr_dynamic_info[num].hd_len = type_length;
pRXCap->hdr_dynamic_info[num].type = type;
pRXCap->hdr_dynamic_info[num].support_flags = buf[pos];
pos++;
for (i = 0; i < type_length - 3; i++) {
pRXCap->hdr_dynamic_info[num].optional_fields[i]
= buf[pos];
pos++;
}
data_end = data_end - (type_length + 1);
}
return 0;
INVALID_DRM_DYNAMIC:
pr_info("[%s] it's not a valid DRM DYNAMIC BLOCK\n", __func__);
return -1;
}
@@ -1449,12 +1512,16 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device,
pRXCap->colorimetry_data =
BlockBuf[offset + 2];
break;
case EXTENSION_DRM_TAG:
Edid_ParsingDRMBlock(pRXCap,
case EXTENSION_DRM_STATIC_TAG:
Edid_ParsingDRMStaticBlock(pRXCap,
&BlockBuf[offset]);
rx_set_hdr_lumi(&BlockBuf[offset],
(BlockBuf[offset] & 0x1f) + 1);
break;
case EXTENSION_DRM_DYNAMIC_TAG:
Edid_ParsingDRMDynamicBlock(pRXCap,
&BlockBuf[offset]);
break;
case EXTENSION_VFPDB_TAG:
/* Just record VFPDB offset address, call Edid_ParsingVFPDB() after DTD
* parsing, in case that
@@ -1819,6 +1886,41 @@ next:
} else
dump_dtd_info(t);
}
static void hdrinfo_to_vinfo(struct vinfo_s *info, struct rx_cap *pRXCap)
{
unsigned int k, l;
info->hdr_info.hdr_support =
(pRXCap->hdr_sup_eotf_sdr << 0) |
(pRXCap->hdr_sup_eotf_hdr << 1) |
(pRXCap->hdr_sup_eotf_smpte_st_2084 << 2) |
(pRXCap->hdr_sup_eotf_hlg << 3);
for (l = 0; l < 4; l++) {
if (pRXCap->hdr_dynamic_info[l].type == 0) {
memset(&info->hdr_info.dynamic_info[l],
0, sizeof(struct hdr_dynamic));
continue;
}
info->hdr_info.dynamic_info[l].type =
pRXCap->hdr_dynamic_info[l].type;
info->hdr_info.dynamic_info[l].of_len =
pRXCap->hdr_dynamic_info[l].hd_len - 3;
info->hdr_info.dynamic_info[l].support_flags =
pRXCap->hdr_dynamic_info[l].support_flags;
for (k = 0; k < (pRXCap->hdr_dynamic_info[l].hd_len - 3); k++) {
info->hdr_info.dynamic_info[l].optional_fields[k] =
pRXCap->hdr_dynamic_info[l].optional_fields[k];
}
}
info->hdr_info.colorimetry_support =
pRXCap->colorimetry_data;
info->hdr_info.lumi_max = pRXCap->hdr_lum_max;
info->hdr_info.lumi_avg = pRXCap->hdr_lum_avg;
info->hdr_info.lumi_min = pRXCap->hdr_lum_min;
pr_info(EDID "update rx hdr info %x at edid parsing\n",
info->hdr_info.hdr_support);
}
int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device)
{
@@ -2015,20 +2117,8 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device)
if (info) {
if (!((strncmp(info->name, "480cvbs", 7) == 0) ||
(strncmp(info->name, "576cvbs", 7) == 0) ||
(strncmp(info->name, "null", 4) == 0))) {
info->hdr_info.hdr_support =
(pRXCap->hdr_sup_eotf_sdr << 0) |
(pRXCap->hdr_sup_eotf_hdr << 1) |
(pRXCap->hdr_sup_eotf_smpte_st_2084 << 2) |
(pRXCap->hdr_sup_eotf_hlg << 3);
info->hdr_info.colorimetry_support =
pRXCap->colorimetry_data;
info->hdr_info.lumi_max = pRXCap->hdr_lum_max;
info->hdr_info.lumi_avg = pRXCap->hdr_lum_avg;
info->hdr_info.lumi_min = pRXCap->hdr_lum_min;
pr_info(EDID "update rx hdr info %x at edid parsing\n",
info->hdr_info.hdr_support);
}
(strncmp(info->name, "null", 4) == 0)))
hdrinfo_to_vinfo(info, pRXCap);
}
return 0;

View File

@@ -389,9 +389,44 @@ static void hdmi_physcial_size_update(struct hdmitx_dev *hdev)
}
static void hdrinfo_to_vinfo(struct vinfo_s *info, struct hdmitx_dev *hdev)
{
unsigned int i, j;
info->hdr_info.hdr_support = (hdev->RXCap.hdr_sup_eotf_sdr << 0)
| (hdev->RXCap.hdr_sup_eotf_hdr << 1)
| (hdev->RXCap.hdr_sup_eotf_smpte_st_2084 << 2)
| (hdev->RXCap.hdr_sup_eotf_hlg << 3);
for (i = 0; i < 4; i++) {
if (hdev->RXCap.hdr_dynamic_info[i].type == 0) {
memset(&info->hdr_info.dynamic_info[i],
0, sizeof(struct hdr_dynamic));
continue;
}
info->hdr_info.dynamic_info[i].type =
hdev->RXCap.hdr_dynamic_info[i].type;
info->hdr_info.dynamic_info[i].of_len =
hdev->RXCap.hdr_dynamic_info[i].hd_len - 3;
info->hdr_info.dynamic_info[i].support_flags =
hdev->RXCap.hdr_dynamic_info[i].support_flags;
for (j = 0; j < hdev->RXCap.hdr_dynamic_info[i].hd_len - 3; j++)
info->hdr_info.dynamic_info[i].optional_fields[j] =
hdev->RXCap.hdr_dynamic_info[i].optional_fields[j];
}
info->hdr_info.colorimetry_support =
hdev->RXCap.colorimetry_data;
info->hdr_info.lumi_max = hdev->RXCap.hdr_lum_max;
info->hdr_info.lumi_avg = hdev->RXCap.hdr_lum_avg;
info->hdr_info.lumi_min = hdev->RXCap.hdr_lum_min;
pr_info(SYS "update rx hdr info %x\n",
info->hdr_info.hdr_support);
}
static int set_disp_mode_auto(void)
{
int ret = -1;
struct vinfo_s *info = NULL;
struct hdmitx_dev *hdev = &hdmitx_device;
struct hdmi_format_para *para = NULL;
@@ -412,19 +447,9 @@ static int set_disp_mode_auto(void)
if (!((strncmp(info->name, "480cvbs", 7) == 0) ||
(strncmp(info->name, "576cvbs", 7) == 0) ||
(strncmp(info->name, "null", 4) == 0))) {
info->hdr_info.hdr_support = (hdev->RXCap.hdr_sup_eotf_sdr << 0)
| (hdev->RXCap.hdr_sup_eotf_hdr << 1)
| (hdev->RXCap.hdr_sup_eotf_smpte_st_2084 << 2)
| (hdev->RXCap.hdr_sup_eotf_hlg << 3);
info->hdr_info.colorimetry_support =
hdev->RXCap.colorimetry_data;
info->hdr_info.lumi_max = hdev->RXCap.hdr_lum_max;
info->hdr_info.lumi_avg = hdev->RXCap.hdr_lum_avg;
info->hdr_info.lumi_min = hdev->RXCap.hdr_lum_min;
pr_info(SYS "update rx hdr info %x\n",
info->hdr_info.hdr_support);
}
(strncmp(info->name, "null", 4) == 0)))
hdrinfo_to_vinfo(info, hdev);
hdmi_physcial_size_update(hdev);
/* If info->name equals to cvbs, then set mode to I mode to hdmi
@@ -2217,27 +2242,47 @@ static ssize_t show_hdr_cap(struct device *dev,
struct device_attribute *attr, char *buf)
{
int pos = 0;
unsigned int i, j;
struct rx_cap *pRXCap = &(hdmitx_device.RXCap);
pos += snprintf(buf + pos, PAGE_SIZE, "Supported EOTF:\n");
pos += snprintf(buf + pos, PAGE_SIZE, " Traditional SDR: %d\n",
pos += snprintf(buf + pos, PAGE_SIZE, "HDR Static Metadata:\n");
pos += snprintf(buf + pos, PAGE_SIZE, " Supported EOTF:\n");
pos += snprintf(buf + pos, PAGE_SIZE, " Traditional SDR: %d\n",
pRXCap->hdr_sup_eotf_sdr);
pos += snprintf(buf + pos, PAGE_SIZE, " Traditional HDR: %d\n",
pos += snprintf(buf + pos, PAGE_SIZE, " Traditional HDR: %d\n",
pRXCap->hdr_sup_eotf_hdr);
pos += snprintf(buf + pos, PAGE_SIZE, " SMPTE ST 2084: %d\n",
pos += snprintf(buf + pos, PAGE_SIZE, " SMPTE ST 2084: %d\n",
pRXCap->hdr_sup_eotf_smpte_st_2084);
pos += snprintf(buf + pos, PAGE_SIZE, " Hybrif Log-Gamma: %d\n",
pos += snprintf(buf + pos, PAGE_SIZE, " Hybrif Log-Gamma: %d\n",
pRXCap->hdr_sup_eotf_hlg);
pos += snprintf(buf + pos, PAGE_SIZE, "Supported SMD type1: %d\n",
pos += snprintf(buf + pos, PAGE_SIZE, " Supported SMD type1: %d\n",
pRXCap->hdr_sup_SMD_type1);
pos += snprintf(buf + pos, PAGE_SIZE, "Luminance Data\n");
pos += snprintf(buf + pos, PAGE_SIZE, " Max: %d\n",
pos += snprintf(buf + pos, PAGE_SIZE, " Luminance Data\n");
pos += snprintf(buf + pos, PAGE_SIZE, " Max: %d\n",
pRXCap->hdr_lum_max);
pos += snprintf(buf + pos, PAGE_SIZE, " Avg: %d\n",
pos += snprintf(buf + pos, PAGE_SIZE, " Avg: %d\n",
pRXCap->hdr_lum_avg);
pos += snprintf(buf + pos, PAGE_SIZE, " Min: %d\n",
pos += snprintf(buf + pos, PAGE_SIZE, " Min: %d\n\n",
pRXCap->hdr_lum_min);
pos += snprintf(buf + pos, PAGE_SIZE, " colorimetry_data: %x\n",
pos += snprintf(buf + pos, PAGE_SIZE, "HDR Dynamic Metadata:");
for (i = 0; i < 4; i++) {
if (pRXCap->hdr_dynamic_info[i].type == 0)
continue;
pos += snprintf(buf + pos, PAGE_SIZE,
"\n metadata_version: %x\n",
pRXCap->hdr_dynamic_info[i].type);
pos += snprintf(buf + pos, PAGE_SIZE,
" support_flags: %x\n",
pRXCap->hdr_dynamic_info[i].support_flags);
pos += snprintf(buf + pos, PAGE_SIZE,
" optional_fields:");
for (j = 0; j <
(pRXCap->hdr_dynamic_info[i].hd_len - 3); j++)
pos += snprintf(buf + pos, PAGE_SIZE, " %x",
pRXCap->hdr_dynamic_info[i].optional_fields[j]);
}
pos += snprintf(buf + pos, PAGE_SIZE, "\n\ncolorimetry_data: %x\n",
pRXCap->colorimetry_data);
return pos;
@@ -3060,11 +3105,8 @@ static enum hdmi_audio_fs aud_samp_rate_map(unsigned int rate)
int i = 0;
for (i = 0; i < ARRAY_SIZE(map_fs); i++) {
if (map_fs[i].rate == rate) {
pr_info(AUD "aout notify rate %d\n",
rate);
if (map_fs[i].rate == rate)
return map_fs[i].fs;
}
}
pr_info(AUD "get FS_MAX\n");
return FS_MAX;
@@ -3102,11 +3144,8 @@ static enum hdmi_audio_sampsize aud_size_map(unsigned int bits)
int i;
for (i = 0; i < ARRAY_SIZE(aud_size_map_ss); i++) {
if (bits == aud_size_map_ss[i].sample_bits) {
pr_info(AUD "aout notify size %d\n",
bits);
if (bits == aud_size_map_ss[i].sample_bits)
return aud_size_map_ss[i].ss;
}
}
pr_info(AUD "get SS_MAX\n");
return SS_MAX;
@@ -3173,7 +3212,7 @@ static int hdmitx_notify_callback_a(struct notifier_block *block,
}
}
if (hdmitx_device.audio_param_update_flag == 0)
pr_info(AUD "no update\n");
;
else
hdmitx_device.audio_notify_flag = 1;
@@ -3284,9 +3323,12 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work)
static void clear_hdr_info(struct hdmitx_dev *hdev)
{
struct vinfo_s *info = hdmitx_get_current_vinfo();
unsigned int i;
if (info) {
info->hdr_info.hdr_support = 0;
for (i = 0; i < 4; i++)
memset(&(info->hdr_info.dynamic_info[i]),
0, sizeof(struct hdr_dynamic));
info->hdr_info.colorimetry_support = 0;
info->hdr_info.lumi_max = 0;
info->hdr_info.lumi_avg = 0;

View File

@@ -360,6 +360,7 @@ static ssize_t vout2_vinfo_show(struct class *class,
{
const struct vinfo_s *info = NULL;
ssize_t len = 0;
unsigned int i, j;
info = get_current_vinfo2();
if (info == NULL)
@@ -409,7 +410,7 @@ static ssize_t vout2_vinfo_show(struct class *class,
info->master_display_info.white_point[1],
info->master_display_info.luminance[0],
info->master_display_info.luminance[1]);
len += sprintf(buf+len, "hdr_info:\n"
len += sprintf(buf+len, "hdr_static_info:\n"
" hdr_support %d\n"
" lumi_max %d\n"
" lumi_avg %d\n"
@@ -418,6 +419,22 @@ static ssize_t vout2_vinfo_show(struct class *class,
info->hdr_info.lumi_max,
info->hdr_info.lumi_avg,
info->hdr_info.lumi_min);
len += sprintf(buf+len, "hdr_dynamic_info:");
for (i = 0; i < 4; i++) {
len += sprintf(buf+len,
"\n metadata_version: %x\n"
" support_flags: %x\n",
info->hdr_info.dynamic_info[i].type,
info->hdr_info.dynamic_info[i].support_flags);
len += sprintf(buf+len, " optional_fields: ");
for (j = 0; j < info->
hdr_info.dynamic_info[i].of_len; j++) {
len += sprintf(buf+len, " %x",
info->hdr_info.dynamic_info[i].
optional_fields[j]);
}
}
len += sprintf(buf+len, "\n");
return len;
}
@@ -523,7 +540,6 @@ static long vout2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
baseinfo.screen_real_height = info->screen_real_height;
baseinfo.video_clk = info->video_clk;
baseinfo.viu_color_fmt = info->viu_color_fmt;
baseinfo.hdr_info = info->hdr_info;
if (copy_to_user(argp, &baseinfo,
sizeof(struct vinfo_base_s)))
ret = -EFAULT;

View File

@@ -434,6 +434,7 @@ static ssize_t vout_vinfo_show(struct class *class,
{
const struct vinfo_s *info = NULL;
ssize_t len = 0;
unsigned int i, j;
info = get_current_vinfo();
if (info == NULL)
@@ -484,7 +485,7 @@ static ssize_t vout_vinfo_show(struct class *class,
info->master_display_info.white_point[1],
info->master_display_info.luminance[0],
info->master_display_info.luminance[1]);
len += sprintf(buf+len, "hdr_info:\n"
len += sprintf(buf+len, "hdr_static_info:\n"
" hdr_support %d\n"
" lumi_max %d\n"
" lumi_avg %d\n"
@@ -493,6 +494,22 @@ static ssize_t vout_vinfo_show(struct class *class,
info->hdr_info.lumi_max,
info->hdr_info.lumi_avg,
info->hdr_info.lumi_min);
len += sprintf(buf+len, "hdr_dynamic_info:");
for (i = 0; i < 4; i++) {
len += sprintf(buf+len,
"\n metadata_version: %x\n"
" support_flags: %x\n",
info->hdr_info.dynamic_info[i].type,
info->hdr_info.dynamic_info[i].support_flags);
len += sprintf(buf+len, " optional_fields: ");
for (j = 0; j <
info->hdr_info.dynamic_info[i].of_len; j++) {
len += sprintf(buf+len, " %x",
info->hdr_info.dynamic_info[i].
optional_fields[j]);
}
}
len += sprintf(buf+len, "\n");
return len;
}
@@ -598,7 +615,6 @@ static long vout_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
baseinfo.screen_real_height = info->screen_real_height;
baseinfo.video_clk = info->video_clk;
baseinfo.viu_color_fmt = info->viu_color_fmt;
baseinfo.hdr_info = info->hdr_info;
if (copy_to_user(argp, &baseinfo,
sizeof(struct vinfo_base_s)))
ret = -EFAULT;

View File

@@ -27,7 +27,7 @@
#include <linux/pinctrl/consumer.h>
/* HDMITX driver version */
#define HDMITX_VER "20180702"
#define HDMITX_VER "20180808"
/* chip type */
#define MESON_CPU_ID_M8B 0
@@ -69,6 +69,13 @@ enum hd_ctrl {
VID_EN, VID_DIS, AUD_EN, AUD_DIS, EDID_EN, EDID_DIS, HDCP_EN, HDCP_DIS,
};
struct hdr_dynamic_struct {
unsigned int type;
unsigned int hd_len;/*hdr_dynamic_length*/
unsigned char support_flags;
unsigned char optional_fields[20];
};
struct rx_cap {
unsigned int native_Mode;
/*video*/
@@ -104,6 +111,7 @@ struct rx_cap {
unsigned char hdr_lum_max;
unsigned char hdr_lum_avg;
unsigned char hdr_lum_min;
struct hdr_dynamic_struct hdr_dynamic_info[4];
unsigned char IDManufacturerName[4];
unsigned char IDProductCode[2];
unsigned char IDSerialNumber[4];

View File

@@ -65,11 +65,34 @@ struct master_display_info_s {
u32 max_content; /* Maximum Content Light Level */
u32 max_frame_average; /* Maximum Frame-average Light Level */
};
/*
*hdr_dynamic_type
* 0x0001: type_1_hdr_metadata_version
* 0x0002: ts_103_433_spec_version
* 0x0003: itu_t_h265_spec_version
* 0x0004: type_4_hdr_metadata_version
*/
struct hdr_dynamic {
unsigned int type;
unsigned char support_flags;
unsigned int of_len; /*optional_fields length*/
unsigned char optional_fields[28];
};
struct hdr_info {
u32 hdr_support; /* RX EDID hdr support types */
/*bit7:BT2020RGB bit6:BT2020YCC bit5:BT2020cYCC bit4:adobeRGB*/
/*bit3:adobeYCC601 bit2:sYCC601 bit1:xvYCC709 bit0:xvYCC601*/
/* RX EDID hdr support types */
u32 hdr_support;
/*
*dynamic_info[0] expresses type1's parameters certainly
*dynamic_info[1] expresses type2's parameters certainly
*dynamic_info[2] expresses type3's parameters certainly
*dynamic_info[3] expresses type4's parameters certainly
*if some types don't exist, the corresponding dynamic_info
*is zero instead of inexistence
*/
struct hdr_dynamic dynamic_info[4];
/*bit7:BT2020RGB bit6:BT2020YCC bit5:BT2020cYCC bit4:adobeRGB*/
/*bit3:adobeYCC601 bit2:sYCC601 bit1:xvYCC709 bit0:xvYCC601*/
u8 colorimetry_support; /* RX EDID colorimetry support types */
u32 lumi_max; /* RX EDID Lumi Max value */
u32 lumi_avg; /* RX EDID Lumi Avg value */
@@ -177,7 +200,6 @@ struct vinfo_base_s {
u32 screen_real_height;
u32 video_clk;
enum color_fmt_e viu_color_fmt;
struct hdr_info hdr_info;
};
struct vinfo_s {