author | Kaifu Hu <kaifu.hu@amlogic.com> | 2018-04-23 06:29:06 (GMT) |
---|---|---|
committer | Xindong Xu <xindong.xu@amlogic.com> | 2018-05-02 02:10:00 (GMT) |
commit | 81d4e869a840681a9caa3a6118d3de08f0e04740 (patch) | |
tree | 2b90ae34d3979c5c9cd527eb3467e0d3c1b477dd | |
parent | 29b92fb3e7d4f508d0467f3c8889321bb1218414 (diff) | |
download | common-81d4e869a840681a9caa3a6118d3de08f0e04740.zip common-81d4e869a840681a9caa3a6118d3de08f0e04740.tar.gz common-81d4e869a840681a9caa3a6118d3de08f0e04740.tar.bz2 |
hdmitx: fix HDR compatibility
PD#161939: HDMITX: fix HDR compatibility.
Fix HDR compatibility for the samsung TV of need to
disable and enable hdmi phy when sdr to hdr.
Change-Id: I5fa648a35ff32f1d4eb544cc12ce759d4c7bcfae
Signed-off-by: Kaifu Hu <kaifu.hu@amlogic.com>
3 files changed, 126 insertions, 39 deletions
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 66b5010..7d7fda9 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 @@ -962,22 +962,45 @@ void hdmitx_video_mute_op(unsigned int flag) } EXPORT_SYMBOL(hdmitx_video_mute_op); +/* + * SDR/HDR uevent + * 1: SDR to HDR + * 0: HDR to SDR + */ +static void hdmitx_sdr_hdr_uevent(struct hdmitx_dev *hdev) +{ + if ((hdev->hdmi_last_hdr_mode == 0) && + (hdev->hdmi_current_hdr_mode != 0)) { + /* SDR -> HDR*/ + hdev->hdmi_last_hdr_mode = hdev->hdmi_current_hdr_mode; + extcon_set_state_sync(hdmitx_extcon_hdr, EXTCON_DISP_HDMI, 1); + } else if ((hdev->hdmi_last_hdr_mode != 0) && + (hdev->hdmi_current_hdr_mode == 0)) { + /* HDR -> SDR*/ + hdev->hdmi_last_hdr_mode = hdev->hdmi_current_hdr_mode; + extcon_set_state_sync(hdmitx_extcon_hdr, EXTCON_DISP_HDMI, 0); + } +} + static void hdr_work_func(struct work_struct *work) { struct hdmitx_dev *hdev = container_of(work, struct hdmitx_dev, work_hdr); - unsigned char DRM_HB[3] = {0x87, 0x1, 26}; - unsigned char DRM_DB[26] = {0x0}; - - hdev->HWOp.SetPacket(HDMI_PACKET_DRM, DRM_DB, DRM_HB); - hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020, CLR_AVI_BT2020); - msleep(1500);/*delay 1.5s*/ - if (hdev->hdr_transfer_feature == T_BT709 && - hdev->hdr_color_feature == C_BT709) + hdev->hdr_color_feature == C_BT709) { + unsigned char DRM_HB[3] = {0x87, 0x1, 26}; + unsigned char DRM_DB[26] = {0x0}; + + hdev->HWOp.SetPacket(HDMI_PACKET_DRM, DRM_DB, DRM_HB); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020, CLR_AVI_BT2020); + msleep(1500);/*delay 1.5s*/ hdev->HWOp.SetPacket(HDMI_PACKET_DRM, NULL, NULL); - /* switch_set_state(&hdmi_hdr, hdev->hdr_src_feature); */ + hdev->hdmi_current_hdr_mode = 0; + hdmitx_sdr_hdr_uevent(hdev); + } else { + hdmitx_sdr_hdr_uevent(hdev); + } } #define GET_LOW8BIT(a) ((a) & 0xff) @@ -1043,8 +1066,6 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data) DRM_DB[24] = GET_LOW8BIT(data->max_frame_average); DRM_DB[25] = GET_HIGH8BIT(data->max_frame_average); - /*eliminate the work of work_hdr*/ - cancel_work(&hdev->work_hdr); /* bt2020 + gamma transfer */ if (hdev->hdr_transfer_feature == T_BT709 && hdev->hdr_color_feature == C_BT2020) { @@ -1069,45 +1090,65 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data) return; } + /*must clear hdr mode*/ + hdev->hdmi_current_hdr_mode = 0; + /* SMPTE ST 2084 and (BT2020 or NON_STANDARD) */ if (hdev->RXCap.hdr_sup_eotf_smpte_st_2084) { if (hdev->hdr_transfer_feature == T_SMPTE_ST_2084 && - hdev->hdr_color_feature == C_BT2020) { - DRM_DB[0] = 0x02; /* SMPTE ST 2084 */ - hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, - DRM_DB, DRM_HB); - hdmitx_device.HWOp.CntlConfig(&hdmitx_device, - CONF_AVI_BT2020, SET_AVI_BT2020); - return; - } else if (hdev->hdr_transfer_feature == T_SMPTE_ST_2084 && - hdev->hdr_color_feature != C_BT2020) { - DRM_DB[0] = 0x02; /* no standard SMPTE ST 2084 */ - hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, - DRM_DB, DRM_HB); - hdmitx_device.HWOp.CntlConfig(&hdmitx_device, - CONF_AVI_BT2020, CLR_AVI_BT2020); - return; - } + hdev->hdr_color_feature == C_BT2020) + hdev->hdmi_current_hdr_mode = 1; + else if (hdev->hdr_transfer_feature == T_SMPTE_ST_2084 && + hdev->hdr_color_feature != C_BT2020) + hdev->hdmi_current_hdr_mode = 2; } /*HLG and BT2020*/ if (hdev->RXCap.hdr_sup_eotf_hlg) { if (hdev->hdr_color_feature == C_BT2020 && (hdev->hdr_transfer_feature == T_BT2020_10 || - hdev->hdr_transfer_feature == T_HLG)) { - DRM_DB[0] = 0x03;/* HLG is 0x03 */ - hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, - DRM_DB, DRM_HB); - hdmitx_device.HWOp.CntlConfig(&hdmitx_device, - CONF_AVI_BT2020, SET_AVI_BT2020); - return; - } + hdev->hdr_transfer_feature == T_HLG)) + hdev->hdmi_current_hdr_mode = 3; } - /*other case*/ - hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, NULL, NULL); - hdmitx_device.HWOp.CntlConfig(&hdmitx_device, CONF_AVI_BT2020, + switch (hdev->hdmi_current_hdr_mode) { + case 1: + /*standard HDR*/ + DRM_DB[0] = 0x02; /* SMPTE ST 2084 */ + hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, + DRM_DB, DRM_HB); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_AVI_BT2020, SET_AVI_BT2020); + break; + case 2: + /*non standard*/ + DRM_DB[0] = 0x02; /* no standard SMPTE ST 2084 */ + hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, + DRM_DB, DRM_HB); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_AVI_BT2020, CLR_AVI_BT2020); + break; + case 3: + /*HLG*/ + DRM_DB[0] = 0x03;/* HLG is 0x03 */ + hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, + DRM_DB, DRM_HB); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, + CONF_AVI_BT2020, SET_AVI_BT2020); + break; + case 0: + default: + /*other case*/ + hdmitx_device.HWOp.SetPacket(HDMI_PACKET_DRM, NULL, NULL); + hdmitx_device.HWOp.CntlConfig(&hdmitx_device, CONF_AVI_BT2020, CLR_AVI_BT2020); + break; + } + + /* if sdr/hdr mode change ,notify uevent to userspace*/ + if (hdev->hdmi_current_hdr_mode != hdev->hdmi_last_hdr_mode) + schedule_work(&hdev->work_hdr); + } static void hdmitx_set_vsif_pkt(enum eotf_type type, @@ -3446,7 +3487,8 @@ static int amhdmitx_device_init(struct hdmitx_dev *hdmi_dev) /* init para for NULL protection */ hdmitx_device.para = hdmi_get_fmt_name("invalid", hdmitx_device.fmt_attr); - + hdmitx_device.hdmi_last_hdr_mode = 0; + hdmitx_device.hdmi_current_hdr_mode = 0; hdmitx_device.unplug_powerdown = 0; hdmitx_device.vic_count = 0; hdmitx_device.auth_process_timer = 0; diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 2f022c1..fea6667 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -2730,6 +2730,37 @@ static void hdmitx_set_fake_vic(struct hdmitx_dev *hdev) set_vmode_clk(hdev); } +static void hdmitx_dump_drm_reg(void) +{ + unsigned int reg_val; + unsigned int reg_addr; + + reg_addr = HDMITX_DWC_FC_AVICONF1; + reg_val = hdmitx_rd_reg(reg_addr); + pr_info("[0x%x]: 0x%x\n", reg_addr, reg_val); + reg_addr = HDMITX_DWC_FC_AVICONF2; + reg_val = hdmitx_rd_reg(reg_addr); + pr_info("[0x%x]: 0x%x\n", reg_addr, reg_val); + reg_addr = HDMITX_DWC_FC_DRM_HB01; + reg_val = hdmitx_rd_reg(reg_addr); + pr_info("[0x%x]: 0x%x\n", reg_addr, reg_val); + reg_addr = HDMITX_DWC_FC_DRM_HB02; + reg_val = hdmitx_rd_reg(reg_addr); + pr_info("[0x%x]: 0x%x\n", reg_addr, reg_val); + + for (reg_addr = HDMITX_DWC_FC_DRM_PB00; + reg_addr <= HDMITX_DWC_FC_DRM_PB26; reg_addr++) { + reg_val = hdmitx_rd_reg(reg_addr); + pr_info("[0x%x]: 0x%x\n", reg_addr, reg_val); + } + reg_addr = HDMITX_DWC_FC_DATAUTO3; + reg_val = hdmitx_rd_reg(reg_addr); + pr_info("[0x%x]: 0x%x\n", reg_addr, reg_val); + reg_addr = HDMITX_DWC_FC_PACKET_TX_EN; + reg_val = hdmitx_rd_reg(reg_addr); + pr_info("[0x%x]: 0x%x\n", reg_addr, reg_val); +} + static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) { char tmpbuf[128]; @@ -2973,6 +3004,17 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) default: break; } + } else if (strncmp(tmpbuf, "hdr_info", 8) == 0) { + pr_info("hdev->hdr_transfer_feature: 0x%x\n", + hdev->hdr_transfer_feature); + pr_info("hdev->hdr_color_feature: 0x%x\n", + hdev->hdr_color_feature); + pr_info("hdev->hdmi_current_hdr_mode: %d\n", + hdev->hdmi_current_hdr_mode); + pr_info("hdev->hdmi_last_hdr_mode: %d\n", + hdev->hdmi_last_hdr_mode); + hdmitx_dump_drm_reg(); + return; } } 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 df03d15..9781a9f 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 @@ -358,6 +358,9 @@ struct hdmitx_dev { unsigned char hdmi_audio_off_flag; enum hdmi_hdr_transfer hdr_transfer_feature; enum hdmi_hdr_color hdr_color_feature; + /* 0: sdr 1:standard HDR 2:non standard 3:HLG*/ + unsigned int hdmi_last_hdr_mode; + unsigned int hdmi_current_hdr_mode; unsigned int dv_src_feature; unsigned int sdr_hdr_feature; unsigned int flag_3dfp:1; |