From: Zongdong Jiao Date: Mon, 18 Feb 2019 09:33:22 +0000 (-0500) Subject: hdmitx: add auto low latency mode(ALLM) [1/1] X-Git-Tag: hardkernel-4.9.236-104~1749 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3aa2991e589c6c03e97c0f886ffe4821082082b3;p=platform%2Fkernel%2Flinux-amlogic.git hdmitx: add auto low latency mode(ALLM) [1/1] PD#SWPL-4705 Problem: Lack ALLM function Solution: Add ALLM function Verify: GXL/P212 If Rx supports ALLM, then echo 1 > /sys/class/amhdmitx/amhdmitx0/allm_mode otherwise it will set failed, cat allm_mode and will get 0. Change-Id: I00233e5a5aac133b405590e7df78c7c4805ed0ef Signed-off-by: Zongdong Jiao --- diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c index 286bd91..81bf931 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c @@ -3428,3 +3428,22 @@ unsigned int hdmi_get_csc_coef( return 1; } +bool is_hdmi14_4k(enum hdmi_vic vic) +{ + bool ret = 0; + + switch (vic) { + case HDMI_3840x2160p24_16x9: + case HDMI_3840x2160p25_16x9: + case HDMI_3840x2160p30_16x9: + case HDMI_4096x2160p24_256x135: + ret = 1; + break; + default: + ret = 0; + break; + } + + return ret; +} + 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 d650bfc..8115b67 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 @@ -397,9 +397,9 @@ int Edid_Parse_check_HDMI_VSDB(struct hdmitx_dev *hdev, if (temp_addr >= VSpecificBoundary) ret = -1; else { - if ((buff[BlockAddr + 1] != 0x03) || - (buff[BlockAddr + 2] != 0x0C) || - (buff[BlockAddr + 3] != 0x0)) + if ((buff[BlockAddr + 1] != GET_OUI_BYTE0(HDMI_IEEE_OUI)) || + (buff[BlockAddr + 2] != GET_OUI_BYTE1(HDMI_IEEE_OUI)) || + (buff[BlockAddr + 3] != GET_OUI_BYTE2(HDMI_IEEE_OUI))) ret = -1; } return ret; @@ -1579,7 +1579,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, if ((BlockBuf[offset] == 0x03) && (BlockBuf[offset+1] == 0x0c) && (BlockBuf[offset+2] == 0x00)) { - pRXCap->IEEEOUI = 0x000c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; pRXCap->ColorDeepSupport = (count > 5) ? BlockBuf[offset+5] : 0; set_vsdb_dc_cap(pRXCap); @@ -1626,7 +1626,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, } else if ((BlockBuf[offset] == 0xd8) && (BlockBuf[offset+1] == 0x5d) && (BlockBuf[offset+2] == 0xc4)) { - pRXCap->HF_IEEEOUI = 0xd85dc4; + pRXCap->HF_IEEEOUI = HF_IEEE_OUI; pRXCap->Max_TMDS_Clock2 = BlockBuf[offset+4]; pRXCap->scdc_present = !!(BlockBuf[offset+5] & (1 << 7)); @@ -1636,6 +1636,11 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, !!(BlockBuf[offset+5] & (1 << 3)); set_vsdb_dc_420_cap(&hdmitx_device->RXCap, &BlockBuf[offset]); + if (count > 7) { + unsigned char b7 = BlockBuf[offset+7]; + + pRXCap->allm = !!(b7 & (1 << 1)); + } } offset += count; /* ignore the remaind. */ @@ -2257,9 +2262,9 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) if ((CheckSum & 0xff) == 0) hdmitx_device->RXCap.IEEEOUI = 0; else - hdmitx_device->RXCap.IEEEOUI = 0x0c03; + hdmitx_device->RXCap.IEEEOUI = HDMI_IEEE_OUI; if (zero_numbers > 120) - hdmitx_device->RXCap.IEEEOUI = 0x0c03; + hdmitx_device->RXCap.IEEEOUI = HDMI_IEEE_OUI; return 0; /* do nothing. */ } @@ -2363,14 +2368,14 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) } if (hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { - pRXCap->IEEEOUI = 0x0c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; pr_info(EDID "find IEEEOUT\n"); } else { pRXCap->IEEEOUI = 0x0; pr_info(EDID "not find IEEEOUT\n"); } - if ((pRXCap->IEEEOUI != 0x0c03) || (pRXCap->IEEEOUI == 0x0) || + if ((pRXCap->IEEEOUI != HDMI_IEEE_OUI) || (pRXCap->IEEEOUI == 0x0) || (pRXCap->VIC_count == 0)) hdmitx_edid_set_default_vic(hdmitx_device); @@ -2381,10 +2386,10 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) pRXCap->IEEEOUI = 0x0; pr_info(EDID "sink is DVI device\n"); } else - pRXCap->IEEEOUI = 0x0c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; if (edid_zero_data(EDID_buf)) - pRXCap->IEEEOUI = 0x0c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; if ((!pRXCap->AUD_count) && (!pRXCap->IEEEOUI)) hdmitx_edid_set_default_aud(hdmitx_device); @@ -2396,7 +2401,7 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) hdmitx_device->tmp_buf[i] = 0; if (!hdmitx_edid_check_valid_blocks(&EDID_buf[0])) { - pRXCap->IEEEOUI = 0x0c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; pr_info(EDID "Invalid edid, consider RX as HDMI device\n"); } /* update RX HDR information */ @@ -2582,7 +2587,7 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, pRXCap = &(hdev->RXCap); /* DVI case, only 8bit */ - if (pRXCap->IEEEOUI != 0x0c03) { + if (pRXCap->IEEEOUI != HDMI_IEEE_OUI) { if (para->cd != COLORDEPTH_24B) return 0; } @@ -2743,7 +2748,7 @@ void hdmitx_edid_clear(struct hdmitx_dev *hdmitx_device) /* Note: in most cases, we think that rx is tv and the default * IEEEOUI is HDMI Identifier */ - pRXCap->IEEEOUI = 0x000c03; + pRXCap->IEEEOUI = HDMI_IEEE_OUI; hdmitx_device->vic_count = 0; hdmitx_device->hdmi_info.vsdb_phy_addr.a = 0; @@ -2935,6 +2940,10 @@ int hdmitx_edid_dump(struct hdmitx_dev *hdmitx_device, char *buffer, "MaxTMDSClock2 %d MHz\n", pRXCap->Max_TMDS_Clock2 * 5); } + if (pRXCap->allm) + pos += snprintf(buffer+pos, buffer_len-pos, "ALLM: %x\n", + pRXCap->allm); + pos += snprintf(buffer+pos, buffer_len-pos, "vLatency: "); if (pRXCap->vLatency == LATENCY_INVALID_UNKNOWN) pos += snprintf(buffer+pos, buffer_len-pos, 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 d85302a..18a9b35 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 @@ -2557,6 +2557,77 @@ static ssize_t store_valid_mode(struct device *dev, return count; } +static ssize_t show_allm_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + struct hdmitx_dev *hdev = &hdmitx_device; + struct rx_cap *pRXCap = &(hdmitx_device.RXCap); + + if (!pRXCap->allm) { /* Rx not support ALLM */ + pos += snprintf(buf + pos, PAGE_SIZE, "0\n\r"); + return pos; + } + + if (hdev->allm_mode == 1) + pos += snprintf(buf + pos, PAGE_SIZE, "game\n\r"); + else if (hdev->allm_mode == 2) + pos += snprintf(buf + pos, PAGE_SIZE, "graphics\n\r"); + else if (hdev->allm_mode == 3) + pos += snprintf(buf + pos, PAGE_SIZE, "photo\n\r"); + else if (hdev->allm_mode == 4) + pos += snprintf(buf + pos, PAGE_SIZE, "cinema\n\r"); + else + pos += snprintf(buf + pos, PAGE_SIZE, "0\n\r"); + + return pos; +} + +static ssize_t store_allm_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct hdmitx_dev *hdev = &hdmitx_device; + struct rx_cap *pRXCap = &hdev->RXCap; + + pr_info("hdmitx: store allm_mode as %s\n", buf); + + if (!pRXCap->allm) /* Rx not support ALLM */ + return count; + +#define CMP_STR(str) (strncmp(buf, str, strlen(str)) == 0) + if (CMP_STR("0")) { + // disable ALLM + hdev->allm_mode = 0; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, CLEAR_ALLM_MODE); + hdmitx_construct_vsif(hdev, VT_ALLM, 0, NULL); + if (is_hdmi14_4k(hdev->cur_VIC)) + hdmitx_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL); + return count; + } + if (CMP_STR("1") || CMP_STR("game") || CMP_STR("graphics") + || CMP_STR("photo") || CMP_STR("cinema")) { + hdmitx_construct_vsif(hdev, VT_ALLM, 1, NULL); + } + if (CMP_STR("1") || CMP_STR("game")) { + hdev->allm_mode = 1; + // enable the default GAME ALLM + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_GAME); + } + if (CMP_STR("graphics")) { + hdev->allm_mode = 2; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_GRAPHICS); + } + if (CMP_STR("photo")) { + hdev->allm_mode = 3; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_PHOTO); + } + if (CMP_STR("cinema")) { + hdev->allm_mode = 4; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_CINEMA); + } + + return count; +} /**/ static ssize_t show_hdr_cap(struct device *dev, @@ -3444,6 +3515,7 @@ static DEVICE_ATTR(hdr_cap, 0444, show_hdr_cap, NULL); static DEVICE_ATTR(dv_cap, 0444, show_dv_cap, NULL); static DEVICE_ATTR(dc_cap, 0444, show_dc_cap, NULL); static DEVICE_ATTR(valid_mode, 0664, show_valid_mode, store_valid_mode); +static DEVICE_ATTR(allm_mode, 0664, show_allm_mode, store_allm_mode); static DEVICE_ATTR(aud_ch, 0664, show_aud_ch, store_aud_ch); static DEVICE_ATTR(avmute, 0664, show_avmute, store_avmute); static DEVICE_ATTR(swap, 0644, show_swap, store_swap); @@ -3821,7 +3893,7 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) rx_repeat_hpd_state(1); hdmitx_get_edid(hdev); hdmi_physcial_size_update(hdev); - if (hdev->RXCap.IEEEOUI != 0x000c03) + if (hdev->RXCap.IEEEOUI != HDMI_IEEE_OUI) hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, DVI_MODE); else @@ -4591,6 +4663,7 @@ static int amhdmitx_probe(struct platform_device *pdev) ret = device_create_file(dev, &dev_attr_support_3d); ret = device_create_file(dev, &dev_attr_dc_cap); ret = device_create_file(dev, &dev_attr_valid_mode); + ret = device_create_file(dev, &dev_attr_allm_mode); #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND register_early_suspend(&hdmitx_early_suspend_handler); @@ -4662,6 +4735,7 @@ static int amhdmitx_remove(struct platform_device *pdev) device_remove_file(dev, &dev_attr_dv_cap); device_remove_file(dev, &dev_attr_dc_cap); device_remove_file(dev, &dev_attr_valid_mode); + device_remove_file(dev, &dev_attr_allm_mode); device_remove_file(dev, &dev_attr_hpd_state); device_remove_file(dev, &dev_attr_rhpd_state); device_remove_file(dev, &dev_attr_max_exceed); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c index 2c5b2e3..181ea70e 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c @@ -871,12 +871,12 @@ static void hdmi_tx_construct_avi_packet( *************************************/ /* - * HDMI Identifier = 0x000c03 + * HDMI Identifier = HDMI_IEEE_OUI 0x000c03 * If not, treated as a DVI Device */ static int is_dvi_device(struct rx_cap *pRXCap) { - if (pRXCap->IEEEOUI != 0x000c03) + if (pRXCap->IEEEOUI != HDMI_IEEE_OUI) return 1; else return 0; @@ -970,6 +970,29 @@ int hdmitx_set_display(struct hdmitx_dev *hdev, enum hdmi_vic VideoCode) hdmi_set_vend_spec_infofram(hdev, 0); else ; + + switch (hdev->RXCap.allm ? hdev->allm_mode : 0) { + case 1: /* game */ + hdmitx_construct_vsif(hdev, VT_ALLM, 1, NULL); + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_GAME); + break; + case 2: /* graphics */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_GRAPHICS); + break; + case 3: /* photo */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_PHOTO); + break; + case 4: /* cinema */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_CINEMA); + break; + default: + break; + } + ret = 0; } } @@ -1001,9 +1024,9 @@ static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdev, for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; - VEN_DB[0] = 0x03; - VEN_DB[1] = 0x0c; - VEN_DB[2] = 0x00; + VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEE_OUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEE_OUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEE_OUI); VEN_DB[3] = 0x00; /* 4k x 2k Spec P156 */ if (VideoCode == HDMI_4k2k_30) { @@ -1037,9 +1060,9 @@ int hdmi_set_3d(struct hdmitx_dev *hdev, int type, unsigned int param) else { for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; - VEN_DB[0] = 0x03; - VEN_DB[1] = 0x0c; - VEN_DB[2] = 0x00; + VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEE_OUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEE_OUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEE_OUI); VEN_DB[3] = 0x40; VEN_DB[4] = type<<4; VEN_DB[5] = param<<4; @@ -1077,3 +1100,74 @@ static void hdmitx_set_spd_info(struct hdmitx_dev *hdev) SPD_DB[24] = 0x1; hdev->HWOp.SetPacket(HDMI_SOURCE_DESCRIPTION, SPD_DB, SPD_HB); } + +static void fill_hdmi4k_vsif_data(enum hdmi_vic vic, unsigned char *DB, + unsigned char *HB) +{ + if (!DB || !HB) + return; + + if (vic == HDMI_4k2k_30) + DB[4] = 0x1; + else if (vic == HDMI_4k2k_25) + DB[4] = 0x2; + else if (vic == HDMI_4k2k_24) + DB[4] = 0x3; + else if (vic == HDMI_4k2k_smpte_24) + DB[4] = 0x4; + else + return; + HB[0] = 0x81; + HB[1] = 0x01; + HB[2] = 0x5; + DB[3] = 0x20; +} + +int hdmitx_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type, + int on, void *param) +{ + unsigned char HB[3] = {0x81, 0x1, 0}; + unsigned char len = 0; /* HB[2] = len */ + unsigned char DB[27]; /* to be fulfilled */ + unsigned int ieeeoui = 0; + + if (!hdev || type >= VT_MAX) + return 0; + memset(DB, 0, sizeof(DB)); + + switch (type) { + case VT_DEFAULT: + break; + case VT_HDMI14_4K: + ieeeoui = HDMI_IEEE_OUI; + len = 5; + if (is_hdmi14_4k(hdev->cur_VIC)) { + fill_hdmi4k_vsif_data(hdev->cur_VIC, DB, HB); + hdmitx_set_avi_vic(0); + } + break; + case VT_ALLM: + ieeeoui = HF_IEEE_OUI; + len = 5; + DB[3] = 0x1; /* Fixed value */ + if (on) { + DB[4] |= 1 << 1; /* set bit1, ALLM_MODE */ + if (is_hdmi14_4k(hdev->cur_VIC)) + hdmitx_set_avi_vic(hdev->cur_VIC); + } else { + DB[4] &= ~(1 << 1); /* clear bit1, ALLM_MODE */ + /* still send out HS_VSIF, no set AVI.VIC = 0 */ + } + break; + default: + break; + } + + HB[2] = len; + DB[0] = GET_OUI_BYTE0(ieeeoui); + DB[1] = GET_OUI_BYTE1(ieeeoui); + DB[2] = GET_OUI_BYTE2(ieeeoui); + + hdev->HWOp.SetDataPacket(HDMI_PACKET_VEND, DB, HB); + return 1; +} 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 576cb87..8e42d76 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 @@ -68,6 +68,8 @@ struct ksv_lists_ { static struct ksv_lists_ tmp_ksv_lists; static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB); +static void hdmitx_set_datapacket(int type, unsigned char *DB, + unsigned char *HB); static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF); static int hdmitx_set_dispmode(struct hdmitx_dev *hdev); @@ -242,6 +244,11 @@ static void config_avmute(unsigned int val) } } +void hdmitx_set_avi_vic(enum hdmi_vic vic) +{ + hdmitx_wr_reg(HDMITX_DWC_FC_AVIVID, vic); +} + static int read_avmute(void) { int val; @@ -600,6 +607,7 @@ static void hdmi_hwi_init(struct hdmitx_dev *hdev) void HDMITX_Meson_Init(struct hdmitx_dev *hdev) { hdev->HWOp.SetPacket = hdmitx_set_packet; + hdev->HWOp.SetDataPacket = hdmitx_set_datapacket; hdev->HWOp.SetAudioInfoFrame = hdmitx_setaudioinfoframe; hdev->HWOp.SetDispMode = hdmitx_set_dispmode; hdev->HWOp.SetAudMode = hdmitx_set_audmode; @@ -2264,6 +2272,40 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) } } +static void hdmitx_set_datapacket(int type, unsigned char *DB, + unsigned char *HB) +{ + int i; +#if 0 + pr_info("HB: %02x %02x %02x\nDB:", HB[0], HB[1], HB[2]); + for (i = 0; (i < 24) && (i < HB[2]); i++) + pr_info(" %02x", DB[i]); + pr_info("\n"); +#endif + switch (type) { + case HDMI_PACKET_VEND: + if ((!DB) || (!HB)) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 0, 3, 1); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 0x0); + return; + } + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, HB[2]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID0, DB[0]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID1, DB[1]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID2, DB[2]); + for (i = 0; (i < 24) && (i < HB[2]); i++) + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD0 + i, DB[3 + i]); + /* Enable VSI packet */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 1, 3, 1); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO1, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO2, 0x10); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 4, 1); + break; + default: + break; + } +} + static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF) @@ -4866,6 +4908,28 @@ static int hdmitx_cntl_config(struct hdmitx_dev *hdev, unsigned int cmd, case CONF_AVI_YQ01: hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, argv, 2, 2); break; + case CONF_ALLM_MODE: + if (argv == CLEAR_ALLM_MODE) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 0, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, 0, 0, 2); + break; + } + if (argv == GET_ALLM_MODE) { + if (hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF2) & (1 << 7)) + ret = hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF3) & 3; + else + ret = -1; + break; + } + /* set ALLM mode */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 1, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, argv & 3, 0, 2); + if (argv == SET_ALLM_PHOTO) { + // TODO + // Extended colorimetry field may be + // sYcc601, AdobeYcc601 or AdobeRGB + } + break; case CONF_EMP_NUMBER: hdmitx_set_reg_bits(HDMITX_TOP_EMP_CNTL0, argv, 16, 16); break; diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h index d35fd9d..ba21dff 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h @@ -32,6 +32,13 @@ #define HDMITX_VIC_MASK 0xff +/* Refer to http://standards-oui.ieee.org/oui/oui.txt */ +#define HDMI_IEEE_OUI 0x000C03 +#define HF_IEEE_OUI 0xC45DD8 +#define GET_OUI_BYTE0(oui) (oui & 0xff) /* Little Endian */ +#define GET_OUI_BYTE1(oui) ((oui >> 8) & 0xff) +#define GET_OUI_BYTE2(oui) ((oui >> 16) & 0xff) + enum hdmi_vic { /* Refer to CEA 861-D */ HDMI_Unknown = 0, 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 b35a836..3f58f55 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 @@ -111,6 +111,11 @@ struct rx_cap { unsigned int dc_30bit_420:1; unsigned int dc_36bit_420:1; unsigned int dc_48bit_420:1; + unsigned int max_frl_rate:4; + unsigned int fpap_start_loc:1; + unsigned int allm:1; + unsigned int mdelta:1; + unsigned int fva:1; unsigned int hdr_sup_eotf_sdr:1; unsigned int hdr_sup_eotf_hdr:1; unsigned int hdr_sup_eotf_smpte_st_2084:1; @@ -325,6 +330,12 @@ struct hdmitx_dev { struct { void (*SetPacket)(int type, unsigned char *DB, unsigned char *HB); + /* In original SetPacket, there are many policys, like + * if ((DB[4] >> 4) == T3D_FRAME_PACKING) + * Need a only pure data packet to call + */ + void (*SetDataPacket)(int type, unsigned char *DB, + unsigned char *HB); void (*SetAudioInfoFrame)(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF); int (*SetDispMode)(struct hdmitx_dev *hdmitx_device); @@ -411,6 +422,8 @@ struct hdmitx_dev { /* 0.1% clock shift, 1080p60hz->59.94hz */ unsigned int frac_rate_policy; unsigned int rxsense_policy; + /* allm_mode: 1/game, 2/graphcis, 3/photo, 4/cinema */ + unsigned int allm_mode; unsigned int sspll; /* configure for I2S: 8ch in, 2ch out */ /* 0: default setting 1:ch0/1 2:ch2/3 3:ch4/5 4:ch6/7 */ @@ -496,6 +509,13 @@ struct hdmitx_dev { #define YCC_RANGE_LIM 0 #define YCC_RANGE_FUL 1 #define YCC_RANGE_RSVD 2 +#define CONF_ALLM_MODE (CMD_CONF_OFFSET + 0X2000 + 0x04) + #define SET_ALLM_GRAPHICS 0 + #define SET_ALLM_PHOTO 1 + #define SET_ALLM_CINEMA 2 + #define SET_ALLM_GAME 3 + #define CLEAR_ALLM_MODE 0xf + #define GET_ALLM_MODE 0x10 #define CONF_VIDEO_MUTE_OP (CMD_CONF_OFFSET + 0x1000 + 0x04) #define VIDEO_MUTE 0x1 #define VIDEO_UNMUTE 0x2 @@ -598,6 +618,42 @@ extern void hdmitx_edid_buf_compare_print(struct hdmitx_dev *hdmitx_device); extern const char *hdmitx_edid_get_native_VIC(struct hdmitx_dev *hdmitx_device); +/* VSIF: Vendor Specific InfoFrame + * It has multiple purposes: + * 1. HDMI1.4 4K, HDMI_VIC=1/2/3/4, 2160p30/25/24hz, smpte24hz, AVI.VIC=0 + * In CTA-861-G, matched with AVI.VIC=95/94/93/98 + * 2. 3D application, TB/SS/FP + * 3. DolbyVision, with Len=0x18 + * 4. HDR10plus + * 5. HDMI20 3D OSD disparity / 3D dual-view / 3D independent view / ALLM + * Some functions are exclusive, but some may compound. + * Consider various state transitions carefully, such as play 3D under HDMI14 + * 4K, exit 3D under 4K, play DV under 4K, enable ALLM under 3D dual-view + */ +enum vsif_type { + /* Below 4 functions are exclusive */ + VT_HDMI14_4K = 1, + VT_T3D_VIDEO, + VT_DOLBYVISION, + VT_HDR10PLUS, + /* Maybe compound 3D dualview + ALLM */ + VT_T3D_OSD_DISPARITY = 0x10, + VT_T3D_DUALVIEW, + VT_T3D_INDEPENDVEW, + VT_ALLM, + /* default: if non-HDMI4K, no any vsif; if HDMI4k, = VT_HDMI14_4K */ + VT_DEFAULT, + VT_MAX, +}; +int hdmitx_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type, int on, + void *param); + +/* if vic is 93 ~ 95, or 98 (HDMI14 4K), return 1 */ +bool is_hdmi14_4k(enum hdmi_vic vic); + +/* set vic to AVI.VIC */ +void hdmitx_set_avi_vic(enum hdmi_vic vic); + /* * HDMI Repeater TX I/F * RX downstream Information from rptx to rprx