dolby: enable DV output in uboot [2/6]
authoryao liu <yao.liu@amlogic.com>
Fri, 9 Aug 2019 13:25:08 +0000 (09:25 -0400)
committerTao Zeng <tao.zeng@amlogic.com>
Fri, 23 Aug 2019 04:25:39 +0000 (21:25 -0700)
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>
drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c
drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h
drivers/amlogic/media/osd/osd_hw.c
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c
drivers/amlogic/media/vout/vout_serve/vout_serve.c
include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h
include/linux/amlogic/media/vout/vinfo.h

index 92e5684..c4dc605 100644 (file)
@@ -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__);
index 75b9444..24c0ec9 100644 (file)
@@ -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;
index 48f7da8..dbe8ffe 100644 (file)
@@ -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)
index 020aacc..4755f0e 100644 (file)
@@ -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))) {
index 3841aae..fa6aaec 100644 (file)
@@ -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))) {
index 5108256..acfbf18 100644 (file)
@@ -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");
index cacea67..422803b 100644 (file)
@@ -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 {
index 26294cb..82c630d 100644 (file)
@@ -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;