summaryrefslogtreecommitdiff
authoryao liu <yao.liu@amlogic.com>2019-08-09 13:25:08 (GMT)
committer Tao Zeng <tao.zeng@amlogic.com>2019-08-23 04:25:39 (GMT)
commit9dd987e9d9e195a9f11d6ece30b729f983a67877 (patch)
tree6aba309a6d770e1e450ccfbf3eeb579bc5fe9706
parent1c879d93ac3bc20a9288efb834dc34c173424fe4 (diff)
downloadcommon-9dd987e9d9e195a9f11d6ece30b729f983a67877.zip
common-9dd987e9d9e195a9f11d6ece30b729f983a67877.tar.gz
common-9dd987e9d9e195a9f11d6ece30b729f983a67877.tar.bz2
dolby: enable DV output in uboot [2/6]
PD#SWPL-392 Problem: transition from uboot to kernel is not smooth Solution: enable DV output in uboot and kernel check if dolby enabled in uboot Verify: G12B/G12A Change-Id: I7f310794cf18a54c15a6f059c460e8dcdf9c25aa Signed-off-by: yao liu <yao.liu@amlogic.com>
Diffstat
-rw-r--r--drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c110
-rw-r--r--drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h1
-rw-r--r--drivers/amlogic/media/osd/osd_hw.c2
-rw-r--r--drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c28
-rw-r--r--drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c3
-rw-r--r--drivers/amlogic/media/vout/vout_serve/vout_serve.c39
-rw-r--r--include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h1
-rw-r--r--include/linux/amlogic/media/vout/vinfo.h1
8 files changed, 169 insertions, 16 deletions
diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c
index 92e5684..c4dc605 100644
--- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c
+++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c
@@ -234,6 +234,8 @@ static unsigned int dolby_vision_flags = FLAG_BYPASS_VPP | FLAG_FORCE_CVM;
module_param(dolby_vision_flags, uint, 0664);
MODULE_PARM_DESC(dolby_vision_flags, "\n dolby_vision_flags\n");
+#define DV_NAME_LEN_MAX 32
+
static unsigned int htotal_add = 0x140;
static unsigned int vtotal_add = 0x40;
static unsigned int vsize_add;
@@ -1043,6 +1045,7 @@ static int is_graphics_output_off(void)
static bool dolby_vision_on;
static bool dolby_vision_core1_on;
static bool dolby_vision_wait_on;
+static bool dolby_vision_on_in_uboot;
static bool dolby_vision_wait_init;
static unsigned int frame_count;
static struct hdr10_param_s hdr10_param;
@@ -3107,7 +3110,7 @@ void enable_dolby_vision(int enable)
0x80200);
/* osd rgb to yuv, vpp out yuv to rgb */
VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0x81);
- pr_dolby_dbg("Dolby Vision TV core turn on\n");
+ pr_info("Dolby Vision TV core turn on\n");
} else if (is_meson_txlx_stbmode()
|| force_stb_mode) {
size = 8 * STB_DMA_TBL_SIZE;
@@ -3209,7 +3212,7 @@ void enable_dolby_vision(int enable)
last_dolby_vision_ll_policy =
dolby_vision_ll_policy;
#endif
- pr_dolby_dbg("Dolby Vision STB cores turn on\n");
+ pr_info("Dolby Vision STB cores turn on\n");
} else if (is_meson_g12() || is_meson_tm2_stbmode()) {
hdr_osd_off();
hdr_vd1_off();
@@ -3354,7 +3357,7 @@ void enable_dolby_vision(int enable)
last_dolby_vision_ll_policy =
dolby_vision_ll_policy;
#endif
- pr_dolby_dbg("Dolby Vision G12a turn on\n");
+ pr_info("Dolby Vision G12a turn on\n");
} else {
VSYNC_WR_DV_REG(VPP_DOLBY_CTRL,
/* cm_datx4_mode */
@@ -3430,7 +3433,7 @@ void enable_dolby_vision(int enable)
last_dolby_vision_ll_policy =
dolby_vision_ll_policy;
#endif
- pr_dolby_dbg("Dolby Vision turn on\n");
+ pr_info("Dolby Vision turn on\n");
}
} else {
if (!dolby_vision_core1_on
@@ -3650,6 +3653,7 @@ void enable_dolby_vision(int enable)
core1_disp_vsize = 0;
dolby_vision_on = false;
force_reset_core2 = true;
+ dolby_vision_on_in_uboot = false;
dolby_vision_core1_on = false;
dolby_vision_wait_on = false;
dolby_vision_wait_init = false;
@@ -4284,7 +4288,6 @@ static int dolby_vision_policy_process(
mode_change = 0;
return mode_change;
}
-
if (((src_format == FORMAT_HLG) ||
(src_format == FORMAT_HDR10PLUS))
&& !(dolby_vision_hdr10_policy & 4)) {
@@ -4316,7 +4319,7 @@ static int dolby_vision_policy_process(
/* TV support DOVI, All -> DOVI */
if (dolby_vision_mode !=
DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) {
- pr_dolby_dbg("src=%d, dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n",
+ pr_info("src=%d, dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n",
src_format);
*mode = DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL;
mode_change = 1;
@@ -4325,7 +4328,7 @@ static int dolby_vision_policy_process(
/* TV support HDR, All -> HDR */
if (dolby_vision_mode !=
DOLBY_VISION_OUTPUT_MODE_HDR10) {
- pr_dolby_dbg("src=%d, dovi output -> DOLBY_VISION_OUTPUT_MODE_HDR10\n",
+ pr_info("src=%d, dovi output -> DOLBY_VISION_OUTPUT_MODE_HDR10\n",
src_format);
*mode = DOLBY_VISION_OUTPUT_MODE_HDR10;
mode_change = 1;
@@ -7065,10 +7068,16 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size,
}
EXPORT_SYMBOL(dolby_vision_process);
+/* when dolby on in uboot, other module cannot get dolby status
+ * in time through dolby_vision_on due to dolby_vision_on
+ * is set in register_dv_functions
+ * Add dolby_vision_on_in_uboot condition for this case.
+ */
bool is_dolby_vision_on(void)
{
return dolby_vision_on
- || dolby_vision_wait_on;
+ || dolby_vision_wait_on
+ || dolby_vision_on_in_uboot;
}
EXPORT_SYMBOL(is_dolby_vision_on);
@@ -7078,7 +7087,6 @@ bool is_dolby_vision_video_on(void)
}
EXPORT_SYMBOL(is_dolby_vision_video_on);
-
bool for_dolby_vision_certification(void)
{
return is_dolby_vision_on() &&
@@ -7154,6 +7162,21 @@ int register_dv_functions(const struct dolby_vision_func_s *func)
unsigned int reg_clk;
unsigned int reg_value;
struct pq_config_s *pq_config;
+ const struct vinfo_s *vinfo = get_current_vinfo();
+
+ /*when dv ko load into kernel, this flag will be disabled
+ *otherwise it will effect hdr module
+ */
+ if (dolby_vision_on_in_uboot) {
+ if (is_vinfo_available(vinfo)) {
+ is_sink_cap_changed(vinfo);
+ dolby_vision_on = true;
+ } else
+ pr_info("sink not available\n");
+ dolby_vision_wait_on = false;
+ dolby_vision_wait_init = false;
+ dolby_vision_on_in_uboot = 0;
+ }
if ((!p_funcs_stb || !p_funcs_tv) && func) {
if (func->control_path && !p_funcs_stb) {
@@ -7550,6 +7573,61 @@ static const char dv_mode_str[6][12] = {
"SDR8",
"BYPASS"
};
+unsigned int dolby_vision_check_enable(void)
+{
+ int dv_mode = 0;
+ /*check if dovi enable in uboot*/
+ if (is_meson_g12()) {
+ if (dolby_vision_on_in_uboot) {
+ dolby_vision_enable = 1;
+ if ((READ_VPP_DV_REG(DOLBY_CORE3_DIAG_CTRL) & 0xff)
+ == 0x20) {
+ /*LL YUV422 mode*/
+ dv_mode = dv_mode_table[1];
+ /*set_dolby_vision_mode(dv_mode);*/
+ dolby_vision_mode = dv_mode;
+ dolby_vision_ll_policy = DOLBY_VISION_LL_YUV422;
+ pr_info("dovi enable in uboot and mode is LL 422\n");
+ } else if ((READ_VPP_DV_REG(DOLBY_CORE3_DIAG_CTRL)
+ & 0xff) == 0x3) {
+ /*LL RGB444 mode*/
+ dv_mode = dv_mode_table[1];
+ /*set_dolby_vision_mode(dv_mode);*/
+ dolby_vision_mode = dv_mode;
+ dolby_vision_ll_policy = DOLBY_VISION_LL_RGB444;
+ pr_info("dovi enable in uboot and mode is LL RGB\n");
+ } else {
+ if (READ_VPP_DV_REG(DOLBY_CORE3_REG_START + 1)
+ == 2) {
+ /*HDR10 mode*/
+ dolby_vision_hdr10_policy = 1;
+ dv_mode = dv_mode_table[3];
+ /*set_dolby_vision_mode(dv_mmde);*/
+ dolby_vision_mode = dv_mode;
+ pr_info("dovi enable in uboot and mode is HDR10\n");
+ } else if (READ_VPP_DV_REG(DOLBY_CORE3_REG_START
+ + 1) == 4) {
+ /*SDR mode*/
+ dv_mode = dv_mode_table[4];
+ /*set_dolby_vision_mode(dv_mode);*/
+ dolby_vision_mode = dv_mode;
+ pr_info("dovi enable in uboot and mode is SDR\n");
+ } else {
+ /*STANDARD RGB444 mode*/
+ dv_mode = dv_mode_table[2];
+ /*set_dolby_vision_mode(dv_mode);*/
+ dolby_vision_mode = dv_mode;
+ dolby_vision_ll_policy =
+ DOLBY_VISION_LL_DISABLE;
+ pr_info("dovi enable in uboot and mode is DV ST\n");
+ }
+ }
+ } else
+ pr_info("dovi disable in uboot\n");
+ }
+
+ return 0;
+}
static ssize_t amdolby_vision_dv_mode_show(struct class *cla,
struct class_attribute *attr, char *buf)
@@ -7860,6 +7938,7 @@ static int amdolby_vision_probe(struct platform_device *pdev)
dolby_vision_init_receiver(pdev);
init_waitqueue_head(&devp->dv_queue);
pr_info("%s: ok\n", __func__);
+ dolby_vision_check_enable();
return 0;
fail_create_device:
@@ -7912,6 +7991,19 @@ static struct platform_driver aml_amdolby_vision_driver = {
.remove = __exit_p(amdolby_vision_remove),
};
+static int __init get_dolby_uboot_status(char *str)
+{
+ char uboot_dolby_status[DV_NAME_LEN_MAX] = {0};
+
+ snprintf(uboot_dolby_status, DV_NAME_LEN_MAX, "%s", str);
+ pr_info("get_dolby_on: %s\n", uboot_dolby_status);
+
+ if (!strcmp(uboot_dolby_status, "1"))
+ dolby_vision_on_in_uboot = 1;
+ return 0;
+}
+__setup("dolby_vision_on=", get_dolby_uboot_status);
+
static int __init amdolby_vision_init(void)
{
pr_info("%s:module init\n", __func__);
diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h
index 75b9444..24c0ec9 100644
--- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h
+++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h
@@ -534,7 +534,6 @@ struct dovi_setting_s {
uint32_t vout_width;
uint32_t vout_height;
u8 vsvdb_tbl[32];
- u8 hdrdb_tbl[7];
struct ext_md_s ext_md;
uint32_t vsvdb_len;
uint32_t vsvdb_changed;
diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c
index 48f7da8..dbe8ffe 100644
--- a/drivers/amlogic/media/osd/osd_hw.c
+++ b/drivers/amlogic/media/osd/osd_hw.c
@@ -8681,8 +8681,6 @@ static void osd_setting_default_hwc(void)
VSYNCOSD_WR_MPEG_REG(VPP_OSD1_IN_SIZE,
blend_vsize << 16 |
blend_hsize);
- VSYNCOSD_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL,
- 0x3, 2, 2);
}
static bool set_old_hwc_freescale(u32 index)
diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c
index 020aacc..4755f0e 100644
--- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c
+++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c
@@ -91,7 +91,23 @@ static unsigned int hdmitx_edid_check_valid_blocks(unsigned char *buf);
static void Edid_DTD_parsing(struct rx_cap *pRXCap, unsigned char *data);
static void hdmitx_edid_set_default_aud(struct hdmitx_dev *hdev);
-static void edid_save_checkvalue(unsigned char *buf, unsigned int block_cnt)
+static int xtochar(int num, unsigned char *checksum)
+{
+ if (((edid_checkvalue[num] >> 4) & 0xf) <= 9)
+ checksum[0] = ((edid_checkvalue[num] >> 4) & 0xf) + '0';
+ else
+ checksum[0] = ((edid_checkvalue[num] >> 4) & 0xf) - 10 + 'a';
+
+ if ((edid_checkvalue[num] & 0xf) <= 9)
+ checksum[1] = (edid_checkvalue[num] & 0xf) + '0';
+ else
+ checksum[1] = (edid_checkvalue[num] & 0xf) - 10 + 'a';
+
+ return 0;
+}
+
+static void edid_save_checkvalue(unsigned char *buf, unsigned int block_cnt,
+ struct rx_cap *RXCap)
{
unsigned int i, length, max;
@@ -105,6 +121,12 @@ static void edid_save_checkvalue(unsigned char *buf, unsigned int block_cnt)
for (i = 0; i < max; i++)
edid_checkvalue[i] = *(buf+(i+1)*128-1);
+
+ RXCap->chksum[0] = '0';
+ RXCap->chksum[1] = 'x';
+
+ for (i = 0; i < 4; i++)
+ xtochar(i, &RXCap->chksum[2 * i + 2]);
}
static int Edid_DecodeHeader(struct hdmitx_info *info, unsigned char *buff)
@@ -2422,7 +2444,7 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device)
if ((!pRXCap->AUD_count) && (!pRXCap->ieeeoui))
hdmitx_edid_set_default_aud(hdmitx_device);
- edid_save_checkvalue(EDID_buf, BlockCount+1);
+ edid_save_checkvalue(EDID_buf, BlockCount + 1, pRXCap);
i = hdmitx_edid_dump(hdmitx_device, (char *)(hdmitx_device->tmp_buf),
HDMI_TMP_BUF_SIZE);
@@ -2435,6 +2457,8 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device)
/* update RX HDR information */
info = get_current_vinfo();
if (info) {
+ /*update hdmi checksum to vout*/
+ memcpy(info->hdmichecksum, pRXCap->chksum, 10);
if (!((strncmp(info->name, "480cvbs", 7) == 0) ||
(strncmp(info->name, "576cvbs", 7) == 0) ||
(strncmp(info->name, "null", 4) == 0))) {
diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c
index 3841aae..fa6aaec 100644
--- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c
+++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c
@@ -456,6 +456,9 @@ static int set_disp_mode_auto(void)
pr_info(SYS "get current mode: %s\n", info->name);
+ /*update hdmi checksum to vout*/
+ memcpy(info->hdmichecksum, hdev->RXCap.chksum, 10);
+
if (!((strncmp(info->name, "480cvbs", 7) == 0) ||
(strncmp(info->name, "576cvbs", 7) == 0) ||
(strncmp(info->name, "null", 4) == 0))) {
diff --git a/drivers/amlogic/media/vout/vout_serve/vout_serve.c b/drivers/amlogic/media/vout/vout_serve/vout_serve.c
index 5108256..acfbf18 100644
--- a/drivers/amlogic/media/vout/vout_serve/vout_serve.c
+++ b/drivers/amlogic/media/vout/vout_serve/vout_serve.c
@@ -75,6 +75,14 @@ static char hdmimode[VMODE_NAME_LEN_MAX] = {
static char cvbsmode[VMODE_NAME_LEN_MAX] = {
'i', 'n', 'v', 'a', 'l', 'i', 'd', '\0'
};
+static char hdmichecksum[VMODE_NAME_LEN_MAX] = {
+ 'i', 'n', 'v', 'a', 'l', 'i', 'd', 'c', 'r', 'c', '\0'
+};
+static char invalidchecksum[VMODE_NAME_LEN_MAX] = {
+ 'i', 'n', 'v', 'a', 'l', 'i', 'd', 'c', 'r', 'c', '\0'
+};
+static char emptychecksum[VMODE_NAME_LEN_MAX] = {0};
+
static enum vmode_e last_vmode = VMODE_MAX;
static int tvout_monitor_flag = 1;
static unsigned int tvout_monitor_timeout_cnt = 20;
@@ -881,14 +889,32 @@ static int refresh_tvout_mode(void)
enum vmode_e cur_vmode = VMODE_MAX;
char cur_mode_str[VMODE_NAME_LEN_MAX];
int hpd_state = 0;
+ struct vinfo_s *info = get_current_vinfo();
if (tvout_monitor_flag == 0)
return 0;
hpd_state = vout_get_hpd_state();
if (hpd_state) {
- cur_vmode = validate_vmode(hdmimode);
- snprintf(cur_mode_str, VMODE_NAME_LEN_MAX, "%s", hdmimode);
+ /* Vout will check the checksum of EDID of uboot and kernel.
+ * If checksum is different. Vout will set null to display/mode.
+ * When systemcontrol bootup, it will set the correct mode and
+ * colorspace according to current EDID from kernel.
+ */
+ VOUTPR("hdmichecksum [%s], kernel hdmichecksum [%s]\n",
+ hdmichecksum, info->hdmichecksum);
+ if ((memcmp(hdmichecksum, info->hdmichecksum, 10)) &&
+ (memcmp(emptychecksum, info->hdmichecksum, 10)) &&
+ (memcmp(invalidchecksum, hdmichecksum, 10))) {
+ VOUTPR("hdmi crc is diff between uboot and kernel\n");
+ cur_vmode = validate_vmode("null");
+ snprintf(cur_mode_str, VMODE_NAME_LEN_MAX, "null");
+
+ } else {
+ cur_vmode = validate_vmode(hdmimode);
+ snprintf(cur_mode_str, VMODE_NAME_LEN_MAX,
+ "%s", hdmimode);
+ }
} else {
cur_vmode = validate_vmode(cvbsmode);
snprintf(cur_mode_str, VMODE_NAME_LEN_MAX, "%s", cvbsmode);
@@ -1195,6 +1221,15 @@ static int __init get_cvbs_mode(char *str)
}
__setup("cvbsmode=", get_cvbs_mode);
+static int __init get_hdmi_checksum(char *str)
+{
+ snprintf(hdmichecksum, VMODE_NAME_LEN_MAX, "%s", str);
+
+ VOUTPR("get hdmi checksum: %s\n", hdmichecksum);
+ return 0;
+}
+__setup("hdmichecksum=", get_hdmi_checksum);
+
MODULE_AUTHOR("Platform-BJ <platform.bj@amlogic.com>");
MODULE_DESCRIPTION("VOUT Server Module");
MODULE_LICENSE("GPL");
diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h
index cacea67..422803b 100644
--- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h
+++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h
@@ -164,6 +164,7 @@ struct rx_cap {
struct raw_block vsd;
/*blk0 check sum*/
unsigned char blk0_chksum;
+ unsigned char chksum[10];
};
struct cts_conftab {
diff --git a/include/linux/amlogic/media/vout/vinfo.h b/include/linux/amlogic/media/vout/vinfo.h
index 26294cb..82c630d 100644
--- a/include/linux/amlogic/media/vout/vinfo.h
+++ b/include/linux/amlogic/media/vout/vinfo.h
@@ -268,6 +268,7 @@ struct vinfo_s {
u32 video_clk;
u32 htotal;
u32 vtotal;
+ unsigned char hdmichecksum[10];
enum vinfo_3d_e info_3d;
enum vout_fr_adj_type_e fr_adj_type;
enum color_fmt_e viu_color_fmt;