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 0f7dda7dc500..1cf6facc91ed 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c @@ -3057,6 +3057,71 @@ struct hdmi_format_para *hdmi_get_fmt_name(char const *name, char const *attr) return para; } +static struct hdmi_format_para tst_para; +static inline void copy_para(struct hdmi_format_para *des, + struct hdmi_format_para *src) +{ + if (!des || !src) + return; + memcpy(des, src, sizeof(struct hdmi_format_para)); +} + +struct hdmi_format_para *hdmi_tst_fmt_name(char const *name, char const *attr) +{ + int i; + char *lname; + enum hdmi_vic vic = HDMI_Unknown; + + copy_para(&tst_para, &fmt_para_non_hdmi_fmt); + if (!name) + return &tst_para; + + for (i = 0; all_fmt_paras[i]; i++) { + lname = all_fmt_paras[i]->name; + if (lname && (strncmp(name, lname, strlen(lname)) == 0)) { + vic = all_fmt_paras[i]->vic; + break; + } + lname = all_fmt_paras[i]->sname; + if (lname && (strncmp(name, lname, strlen(lname)) == 0)) { + vic = all_fmt_paras[i]->vic; + break; + } + } + if ((vic != HDMI_Unknown) && (i != sizeof(all_fmt_paras) / + sizeof(struct hdmi_format_para *))) { + copy_para(&tst_para, all_fmt_paras[i]); + memset(&tst_para.ext_name[0], 0, sizeof(tst_para.ext_name)); + memcpy(&tst_para.ext_name[0], name, sizeof(tst_para.ext_name)); + hdmi_parse_attr(&tst_para, name); + hdmi_parse_attr(&tst_para, attr); + } else { + copy_para(&tst_para, &fmt_para_non_hdmi_fmt); + hdmi_parse_attr(&tst_para, name); + hdmi_parse_attr(&tst_para, attr); + } + if (strstr(name, "420")) + tst_para.cs = COLORSPACE_YUV420; + + /* only 2160p60/50hz smpte60/50hz have Y420 mode */ + if (tst_para.cs == COLORSPACE_YUV420) { + switch ((tst_para.vic) & 0xff) { + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + case HDMI_3840x2160p50_64x27: + case HDMI_3840x2160p60_64x27: + break; + default: + copy_para(&tst_para, &fmt_para_non_hdmi_fmt); + break; + } + } + + return &tst_para; +} + struct vinfo_s *hdmi_get_valid_vinfo(char *mode) { int i; @@ -3632,3 +3697,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 ac12760e2d7d..01fa4ab0a233 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) @@ -395,9 +417,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_IEEEOUI)) || + (buff[BlockAddr + 2] != GET_OUI_BYTE1(HDMI_IEEEOUI)) || + (buff[BlockAddr + 3] != GET_OUI_BYTE2(HDMI_IEEEOUI))) ret = -1; } return ret; @@ -1532,7 +1554,6 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, pRXCap->number_of_dtd += BlockBuf[3] & 0xf; pRXCap->native_VIC = 0xff; - pRXCap->AUD_count = 0; Edid_Y420CMDB_Reset(&(hdmitx_device->hdmi_info)); @@ -1578,7 +1599,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_IEEEOUI; pRXCap->ColorDeepSupport = (count > 5) ? BlockBuf[offset+5] : 0; set_vsdb_dc_cap(pRXCap); @@ -1625,7 +1646,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_IEEEOUI; pRXCap->Max_TMDS_Clock2 = BlockBuf[offset+4]; pRXCap->scdc_present = !!(BlockBuf[offset+5] & (1 << 7)); @@ -1635,6 +1656,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. */ @@ -1741,7 +1767,7 @@ static void hdmitx_edid_set_default_aud(struct hdmitx_dev *hdev) pRXCap->RxAudioCap[0].audio_format_code = 1; /* PCM */ pRXCap->RxAudioCap[0].channel_num_max = 1; /* 2ch */ pRXCap->RxAudioCap[0].freq_cc = 7; /* 32/44.1/48 kHz */ - pRXCap->RxAudioCap[0].cc3 = 7; /* 16/20/24 bit */ + pRXCap->RxAudioCap[0].cc3 = 1; /* 16bit */ } /* add default VICs for DVI case */ @@ -2040,6 +2066,35 @@ next: dump_dtd_info(t); } +static void edid_check_pcm_declare(struct rx_cap *pRXCap) +{ + int idx_pcm = 0; + int i; + + if (!pRXCap->AUD_count) + return; + + /* Try to find more than 1 PCMs, RxAudioCap[0] is always basic audio */ + for (i = 1; i < pRXCap->AUD_count; i++) { + if (pRXCap->RxAudioCap[i].audio_format_code == + pRXCap->RxAudioCap[0].audio_format_code) { + idx_pcm = i; + break; + } + } + + /* Remove basic audio */ + if (idx_pcm) { + for (i = 0; i < pRXCap->AUD_count - 1; i++) + memcpy(&pRXCap->RxAudioCap[i], + &pRXCap->RxAudioCap[i + 1], + sizeof(struct rx_audiocap)); + /* Clear the last audio declaration */ + memset(&pRXCap->RxAudioCap[i], 0, sizeof(struct rx_audiocap)); + pRXCap->AUD_count--; + } +} + static void hdrinfo_to_vinfo(struct vinfo_s *info, struct rx_cap *pRXCap) { unsigned int k, l; @@ -2257,9 +2312,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_IEEEOUI; if (zero_numbers > 120) - hdmitx_device->RXCap.ieeeoui = 0x0c03; + hdmitx_device->RXCap.ieeeoui = HDMI_IEEEOUI; return 0; /* do nothing. */ } @@ -2308,7 +2363,7 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) hdmitx_edid_block_parse(hdmitx_device, &(EDID_buf[i*128])); } - + edid_check_pcm_declare(&hdmitx_device->RXCap); /* * Because DTDs are not able to represent some Video Formats, which can be * represented as SVDs and might be preferred by Sinks, the first DTD in the @@ -2363,14 +2418,14 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) } if (hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { - pRXCap->ieeeoui = 0x0c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; 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_IEEEOUI) || (pRXCap->ieeeoui == 0x0) || (pRXCap->VIC_count == 0)) hdmitx_edid_set_default_vic(hdmitx_device); @@ -2381,27 +2436,29 @@ 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_IEEEOUI; if (edid_zero_data(EDID_buf)) - pRXCap->ieeeoui = 0x0c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; 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); hdmitx_device->tmp_buf[i] = 0; if (!hdmitx_edid_check_valid_blocks(&EDID_buf[0])) { - pRXCap->ieeeoui = 0x0c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; pr_info(EDID "Invalid edid, consider RX as HDMI device\n"); } /* 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))) { @@ -2615,7 +2672,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_IEEEOUI) { if (para->cd != COLORDEPTH_24B) return 0; } @@ -2781,7 +2838,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_IEEEOUI; hdmitx_device->vic_count = 0; hdmitx_device->hdmi_info.vsdb_phy_addr.a = 0; @@ -2973,6 +3030,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 aba8cfd0a492..d47c58843acf 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 @@ -73,13 +73,14 @@ static int set_disp_mode_auto(void); static void hdmitx_get_edid(struct hdmitx_dev *hdev); static void hdmitx_set_drm_pkt(struct master_display_info_s *data); static void hdmitx_set_vsif_pkt(enum eotf_type type, enum mode_type - tunnel_mode, struct dv_vsif_para *data); + tunnel_mode, struct dv_vsif_para *data, bool switch_to_sdr); static void hdmitx_set_hdr10plus_pkt(unsigned int flag, struct hdr10plus_para *data); static void hdmitx_set_emp_pkt(unsigned char *data, unsigned int type, unsigned int size); static int check_fbc_special(unsigned char *edid_dat); static struct vinfo_s *hdmitx_get_current_vinfo(void); +static void hdmitx_fmt_attr(struct hdmitx_dev *hdev); static DEFINE_MUTEX(setclk_mutex); static DEFINE_MUTEX(getedid_mutex); @@ -124,6 +125,7 @@ struct extcon_dev *hdmitx_extcon_power; struct extcon_dev *hdmitx_extcon_hdr; struct extcon_dev *hdmitx_extcon_rxsense; struct extcon_dev *hdmitx_extcon_hdcp; +struct extcon_dev *hdmitx_extcon_cedst; static struct hdmi_cea_timing custom_timing; struct hdmi_cea_timing *get_custom_timing(void) @@ -476,6 +478,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))) { @@ -499,6 +504,8 @@ static int set_disp_mode_auto(void) hdev->HWOp.CntlConfig(hdev, CONF_CLR_VSDB_PACKET, 0); hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE); hdev->para = hdmi_get_fmt_name("invalid", hdev->fmt_attr); + if (hdev->cedst_policy) + cancel_delayed_work(&hdev->work_cedst); return -1; } strncpy(mode, info->name, sizeof(mode)); @@ -607,6 +614,10 @@ static int set_disp_mode_auto(void) } } hdmitx_set_audio(hdev, &(hdev->cur_audio_param)); + if (hdev->cedst_policy) { + cancel_delayed_work(&hdev->work_cedst); + queue_delayed_work(hdev->cedst_wq, &hdev->work_cedst, 0); + } hdev->output_blank_flag = 1; hdev->ready = 1; return ret; @@ -634,8 +645,12 @@ static ssize_t show_attr(struct device *dev, struct device_attribute *attr, char *buf) { int pos = 0; - - pos += snprintf(buf+pos, PAGE_SIZE, "%s\n\r", hdmitx_device.fmt_attr); + if (!memcmp(hdmitx_device.fmt_attr, "default,", 7)) { + memset(hdmitx_device.fmt_attr, 0, + sizeof(hdmitx_device.fmt_attr)); + hdmitx_fmt_attr(&hdmitx_device); + } + pos += snprintf(buf+pos, PAGE_SIZE, "%s\n", hdmitx_device.fmt_attr); return pos; } @@ -644,6 +659,14 @@ ssize_t store_attr(struct device *dev, { strncpy(hdmitx_device.fmt_attr, buf, sizeof(hdmitx_device.fmt_attr)); hdmitx_device.fmt_attr[15] = '\0'; + if (!memcmp(hdmitx_device.fmt_attr, "rgb", 3)) + hdmitx_device.para->cs = COLORSPACE_RGB444; + else if (!memcmp(hdmitx_device.fmt_attr, "422", 3)) + hdmitx_device.para->cs = COLORSPACE_YUV422; + else if (!memcmp(hdmitx_device.fmt_attr, "420", 3)) + hdmitx_device.para->cs = COLORSPACE_YUV420; + else + hdmitx_device.para->cs = COLORSPACE_YUV444; return count; } /*aud_mode attr*/ @@ -1413,8 +1436,25 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data) } +static void update_current_para(struct hdmitx_dev *hdev) +{ + struct vinfo_s *info = NULL; + unsigned char mode[32]; + + info = hdmitx_get_current_vinfo(); + if (!info) + return; + + strncpy(mode, info->name, sizeof(mode)); + if (strstr(hdev->fmt_attr, "420")) { + if (!strstr(mode, "420")) + strncat(mode, "420", 3); + } + hdev->para = hdmi_get_fmt_name(mode, hdev->fmt_attr); +} + static void hdmitx_set_vsif_pkt(enum eotf_type type, - enum mode_type tunnel_mode, struct dv_vsif_para *data) + enum mode_type tunnel_mode, struct dv_vsif_para *data, bool signal_sdr) { struct hdmitx_dev *hdev = &hdmitx_device; struct dv_vsif_para para = {0}; @@ -1511,14 +1551,18 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type, else hdev->HWOp.SetPacket( HDMI_PACKET_VEND, NULL, NULL); - hdev->HWOp.CntlConfig(hdev, - CONF_AVI_RGBYCC_INDIC, hdev->para->cs); - hdev->HWOp.CntlConfig(hdev, - CONF_AVI_Q01, RGB_RANGE_LIM); - hdev->HWOp.CntlConfig(hdev, - CONF_AVI_YQ01, YCC_RANGE_LIM); - hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020, - CLR_AVI_BT2020);/*BT709*/ + if (signal_sdr) { + pr_info("hdmitx: H14b VSIF, switching signal to SDR\n"); + update_current_para(hdev); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, hdev->para->cs); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_Q01, RGB_RANGE_DEFAULT); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_YQ01, YCC_RANGE_LIM); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020, + CLR_AVI_BT2020);/*BT709*/ + } } } @@ -1530,6 +1574,8 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type, if (data == NULL) data = ¶ + len = 0x1b; + /*4k vsif package */ if ((vic == HDMI_3840x2160p30_16x9) || (vic == HDMI_3840x2160p25_16x9) || @@ -1540,14 +1586,13 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type, switch (type) { case EOTF_T_DOLBYVISION: case EOTF_T_LL_MODE: - len = 0x1b; hdev->dv_src_feature = 1; break; case EOTF_T_HDR10: case EOTF_T_SDR: case EOTF_T_NULL: default: - len = 0x5; + hdev->dv_src_feature = 0; break; } @@ -1632,14 +1677,18 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type, } else hdev->HWOp.SetPacket( HDMI_PACKET_VEND, NULL, NULL); - hdev->HWOp.CntlConfig(hdev, - CONF_AVI_RGBYCC_INDIC, hdev->para->cs); - hdev->HWOp.CntlConfig(hdev, - CONF_AVI_Q01, RGB_RANGE_LIM); - hdev->HWOp.CntlConfig(hdev, - CONF_AVI_YQ01, YCC_RANGE_LIM); - hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020, + + if (signal_sdr) { + pr_info("hdmitx: Dolby VSIF, switching signal to SDR\n"); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_RGBYCC_INDIC, hdev->para->cs); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_Q01, RGB_RANGE_DEFAULT); + hdev->HWOp.CntlConfig(hdev, + CONF_AVI_YQ01, YCC_RANGE_LIM); + hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020, CLR_AVI_BT2020);/*BT709*/ + } } } } @@ -2076,7 +2125,7 @@ static ssize_t store_config(struct device *dev, data.features = 0x00091200; hdmitx_set_drm_pkt(&data); } else if (strncmp(buf, "vsif", 4) == 0) - hdmitx_set_vsif_pkt(buf[4] - '0', buf[5] == '1', NULL); + hdmitx_set_vsif_pkt(buf[4] - '0', buf[5] == '1', NULL, true); else if (strncmp(buf, "emp", 3) == 0) { if (hdmitx_device.chip_type >= MESON_CPU_ID_G12A) hdmitx_set_emp_pkt(NULL, 1, 1); @@ -2599,7 +2648,7 @@ static ssize_t show_valid_mode(struct device *dev, valid_mode); return pos; } - para = hdmi_get_fmt_name(cvalid_mode, cvalid_mode); + para = hdmi_tst_fmt_name(cvalid_mode, cvalid_mode); } if (para) { pr_info(SYS "sname = %s\n", para->sname); @@ -2624,6 +2673,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, @@ -2959,6 +3079,84 @@ static ssize_t show_rxsense_policy(struct device *dev, return pos; } +/* cedst_policy: 0, no CED feature + * 1, auto mode, depends on RX scdc_present + * 2, forced CED feature + */ +static ssize_t store_cedst_policy(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int val = 0; + struct hdmitx_dev *hdev = &hdmitx_device; + + if (isdigit(buf[0])) { + val = buf[0] - '0'; + pr_info("hdmitx: set cedst_policy as %d\n", val); + if ((val == 0) || (val == 1) || (val == 2)) { + hdev->cedst_policy = val; + if (val == 1) { /* Auto mode, depends on Rx */ + /* check RX scdc_present */ + if (hdev->RXCap.scdc_present) + hdev->cedst_policy = 1; + else + hdev->cedst_policy = 0; + } + if (val == 2) /* Force mode */ + hdev->cedst_policy = 1; + /* assgin cedst_en from dts or here */ + hdev->cedst_en = hdev->cedst_policy; + } else + pr_info("only accept as 0, 1(auto), or 2(force)\n"); + } + if (hdev->cedst_policy) + queue_delayed_work(hdev->cedst_wq, &hdev->work_cedst, 0); + else + cancel_delayed_work(&hdev->work_cedst); + + + return count; +} + +static ssize_t show_cedst_policy(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + pos += snprintf(buf + pos, PAGE_SIZE, "%d\n", + hdmitx_device.cedst_policy); + + return pos; +} + +static ssize_t show_cedst_count(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + struct ced_cnt *ced = &hdmitx_device.ced_cnt; + struct scdc_locked_st *ch_st = &hdmitx_device.chlocked_st; + + if (!ch_st->clock_detected) + pos += snprintf(buf + pos, PAGE_SIZE, "clock undetected\n"); + if (!ch_st->ch0_locked) + pos += snprintf(buf + pos, PAGE_SIZE, "CH0 unlocked\n"); + if (!ch_st->ch1_locked) + pos += snprintf(buf + pos, PAGE_SIZE, "CH1 unlocked\n"); + if (!ch_st->ch2_locked) + pos += snprintf(buf + pos, PAGE_SIZE, "CH2 unlocked\n"); + if (ced->ch0_valid && ced->ch0_cnt) + pos += snprintf(buf + pos, PAGE_SIZE, "CH0 ErrCnt 0x%x\n", + ced->ch0_cnt); + if (ced->ch1_valid && ced->ch1_cnt) + pos += snprintf(buf + pos, PAGE_SIZE, "CH1 ErrCnt 0x%x\n", + ced->ch1_cnt); + if (ced->ch2_valid && ced->ch2_cnt) + pos += snprintf(buf + pos, PAGE_SIZE, "CH2 ErrCnt 0x%x\n", + ced->ch2_cnt); + memset(ced, 0, sizeof(*ced)); + + return pos; +} + static ssize_t store_sspll(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -3512,6 +3710,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); @@ -3521,6 +3720,8 @@ static DEVICE_ATTR(sspll, 0664, show_sspll, store_sspll); static DEVICE_ATTR(frac_rate_policy, 0664, show_frac_rate, store_frac_rate); static DEVICE_ATTR(rxsense_policy, 0644, show_rxsense_policy, store_rxsense_policy); +static DEVICE_ATTR(cedst_policy, 0664, show_cedst_policy, store_cedst_policy); +static DEVICE_ATTR(cedst_count, 0444, show_cedst_count, NULL); static DEVICE_ATTR(hdcp_clkdis, 0664, show_hdcp_clkdis, store_hdcp_clkdis); static DEVICE_ATTR(hdcp_pwr, 0664, show_hdcp_pwr, store_hdcp_pwr); static DEVICE_ATTR(hdcp_byp, 0200, NULL, store_hdcp_byp); @@ -3613,10 +3814,14 @@ static int hdmitx_module_disable(enum vmode_e cur_vmod) hdev->HWOp.CntlConfig(hdev, CONF_CLR_AVI_PACKET, 0); hdev->HWOp.CntlConfig(hdev, CONF_CLR_VSDB_PACKET, 0); hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE); - if (hdev->para->hdmitx_vinfo.viu_mux == VIU_MUX_ENCI) - hdmitx_disable_vclk2_enci(hdev); + hdmitx_disable_clk(hdev); hdev->para = hdmi_get_fmt_name("invalid", hdev->fmt_attr); hdmitx_validate_vmode("null"); + if (hdev->cedst_policy) + cancel_delayed_work(&hdev->work_cedst); + if (hdev->rxsense_policy) + queue_delayed_work(hdmitx_device.rxsense_wq, + &hdmitx_device.work_rxsense, 0); return 0; } @@ -3866,9 +4071,23 @@ static void hdmitx_rxsense_process(struct work_struct *work) queue_delayed_work(hdev->rxsense_wq, &hdev->work_rxsense, HZ); } +static void hdmitx_cedst_process(struct work_struct *work) +{ + int ced; + struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, + struct hdmitx_dev, work_cedst); + + ced = hdev->HWOp.CntlMisc(hdev, MISC_TMDS_CEDST, 0); + /* firstly send as 0, then real ced, A trigger signal */ + extcon_set_state_sync(hdmitx_extcon_cedst, EXTCON_DISP_HDMI, 0); + extcon_set_state_sync(hdmitx_extcon_cedst, EXTCON_DISP_HDMI, ced); + queue_delayed_work(hdev->cedst_wq, &hdev->work_cedst, HZ); +} + static void hdmitx_hpd_plugin_handler(struct work_struct *work) { char bksv_buf[5]; + struct vinfo_s *info = NULL; struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, struct hdmitx_dev, work_hpd_plugin); @@ -3887,6 +4106,7 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) if (hdev->repeater_tx) rx_repeat_hpd_state(1); hdmitx_get_edid(hdev); + hdev->cedst_policy = hdev->cedst_en & hdev->RXCap.scdc_present; hdmi_physcial_size_update(hdev); #if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) @@ -3924,14 +4144,19 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) rx_set_receive_hdcp(bksv_buf, 1, 1, 0, 0); } - set_disp_mode_auto(); - hdmitx_set_audio(hdev, &(hdev->cur_audio_param)); + info = hdmitx_get_current_vinfo(); + if (info && (info->mode == VMODE_HDMI)) + hdmitx_set_audio(hdev, &(hdev->cur_audio_param)); hdev->hpd_state = 1; hdmitx_notify_hpd(hdev->hpd_state); extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 1); extcon_set_state_sync(hdmitx_extcon_audio, EXTCON_DISP_HDMI, 1); mutex_unlock(&setclk_mutex); + /* Should be started at end of output */ + cancel_delayed_work(&hdev->work_cedst); + if (hdev->cedst_policy) + queue_delayed_work(hdev->cedst_wq, &hdev->work_cedst, 0); } static void clear_rx_vinfo(struct hdmitx_dev *hdev) @@ -3956,6 +4181,8 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) hdev->HWOp.CntlDDC(hdev, DDC_HDCP_MUX_INIT, 1); hdev->HWOp.CntlDDC(hdev, DDC_HDCP_OP, HDCP14_OFF); mutex_lock(&setclk_mutex); + if (hdev->cedst_policy) + cancel_delayed_work(&hdev->work_cedst); pr_info(SYS "plugout\n"); if (!!(hdev->HWOp.CntlMisc(hdev, MISC_HPD_GPI_ST, 0))) { pr_info(SYS "hpd gpio high\n"); @@ -3964,7 +4191,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) return; } /*after plugout, DV mode can't be supported*/ - hdmitx_set_vsif_pkt(0, 0, NULL); + hdmitx_set_vsif_pkt(0, 0, NULL, true); hdmitx_set_hdr10plus_pkt(0, NULL); hdev->ready = 0; if (hdev->repeater_tx) @@ -4024,6 +4251,7 @@ int tv_audio_support(int type, struct rx_cap *pRXCap) static int hdmi_task_handle(void *data) { + struct vinfo_s *info = NULL; struct hdmitx_dev *hdmitx_device = (struct hdmitx_dev *)data; hdmitx_extcon_hdmi->state = !!(hdmitx_device->HWOp.CntlMisc( @@ -4050,6 +4278,10 @@ static int hdmi_task_handle(void *data) hdmitx_device->rxsense_wq = alloc_workqueue(hdmitx_extcon_rxsense->name, WQ_SYSFS | WQ_FREEZABLE, 0); INIT_DELAYED_WORK(&hdmitx_device->work_rxsense, hdmitx_rxsense_process); + /* for cedst feature */ + hdmitx_device->cedst_wq = alloc_workqueue(hdmitx_extcon_cedst->name, + WQ_SYSFS | WQ_FREEZABLE, 0); + INIT_DELAYED_WORK(&hdmitx_device->work_cedst, hdmitx_cedst_process); hdmitx_device->tx_aud_cfg = 1; /* default audio configure is on */ @@ -4058,11 +4290,19 @@ static int hdmi_task_handle(void *data) hdmitx_device->HWOp.SetupIRQ(hdmitx_device); /* Trigger HDMITX IRQ*/ - hdmitx_device->HWOp.CntlMisc(hdmitx_device, MISC_HPD_MUX_OP, PIN_UNMUX); - mdelay(20); hdmitx_device->HWOp.CntlMisc(hdmitx_device, MISC_HPD_MUX_OP, PIN_MUX); + if (hdmitx_device->HWOp.CntlMisc(hdmitx_device, MISC_HPD_GPI_ST, 0)) + hdmitx_device->HWOp.CntlMisc(hdmitx_device, + MISC_TRIGGER_HPD, 0); hdmitx_device->hdmi_init = 1; + info = hdmitx_get_current_vinfo(); + if (!info || !info->name) + return 0; + if (info->mode == VMODE_HDMI) + hdmitx_device->para = hdmi_get_fmt_name(info->name, + hdmitx_device->fmt_attr); + return 0; } @@ -4122,7 +4362,7 @@ static int get_dt_vend_init_data(struct device_node *np, return 0; } -static void hdmitx_init_fmt_attr(struct hdmitx_dev *hdev) +static void hdmitx_fmt_attr(struct hdmitx_dev *hdev) { if (strlen(hdev->fmt_attr) >= 8) { pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr); @@ -4168,6 +4408,20 @@ static void hdmitx_init_fmt_attr(struct hdmitx_dev *hdev) pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr); } +static void hdmitx_init_fmt_attr(struct hdmitx_dev *hdev) +{ + if (strlen(hdev->fmt_attr) >= 8) { + pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr); + return; + } + if ((hdev->para->cd == COLORDEPTH_RESERVED) && + (hdev->para->cs == COLORSPACE_RESERVED)) { + strcpy(hdev->fmt_attr, "default"); + } else + hdmitx_fmt_attr(hdev); + pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr); +} + /* for notify to cec */ static BLOCKING_NOTIFIER_HEAD(hdmitx_event_notify_list); int hdmitx_event_notifier_regist(struct notifier_block *nb) @@ -4228,6 +4482,7 @@ void hdmitx_extcon_register(struct platform_device *pdev, struct device *dev) ret = extcon_dev_register(edev); if (ret < 0) { pr_info(SYS "failed to register hdmitx extcon hdmi\n"); + extcon_dev_free(edev); return; } hdmitx_extcon_hdmi = edev; @@ -4238,13 +4493,13 @@ void hdmitx_extcon_register(struct platform_device *pdev, struct device *dev) pr_info(SYS "failed to allocate hdmitx extcon audio\n"); return; } - edev->dev.parent = dev; edev->name = "hdmitx_extcon_audio"; dev_set_name(&edev->dev, "hdmi_audio"); ret = extcon_dev_register(edev); if (ret < 0) { pr_info(SYS "failed to register hdmitx extcon audio\n"); + extcon_dev_free(edev); return; } hdmitx_extcon_audio = edev; @@ -4255,13 +4510,13 @@ void hdmitx_extcon_register(struct platform_device *pdev, struct device *dev) pr_info(SYS "failed to allocate hdmitx extcon power\n"); return; } - edev->dev.parent = dev; edev->name = "hdmitx_extcon_power"; dev_set_name(&edev->dev, "hdmi_power"); ret = extcon_dev_register(edev); if (ret < 0) { pr_info(SYS "failed to register extcon power\n"); + extcon_dev_free(edev); return; } hdmitx_extcon_power = edev; @@ -4272,30 +4527,47 @@ void hdmitx_extcon_register(struct platform_device *pdev, struct device *dev) pr_info(SYS "failed to allocate hdmitx extcon hdr\n"); return; } - edev->dev.parent = dev; edev->name = "hdmitx_extcon_hdr"; dev_set_name(&edev->dev, "hdmi_hdr"); ret = extcon_dev_register(edev); if (ret < 0) { pr_info(SYS "failed to register hdmitx extcon hdr\n"); + extcon_dev_free(edev); return; } hdmitx_extcon_hdr = edev; + /*hdmitx extcon CED */ + edev = extcon_dev_allocate(hdmi_cable); + if (IS_ERR(edev)) { + pr_info(SYS "failed to allocate extcon rxsense\n"); + return; + } + edev->dev.parent = dev; + edev->name = "hdmitx_extcon_cedst"; + dev_set_name(&edev->dev, "hdmi_cedst"); + ret = extcon_dev_register(edev); + if (ret < 0) { + pr_info(SYS "failed to register extcon cedst\n"); + extcon_dev_free(edev); + return; + } + hdmitx_extcon_cedst = edev; + /*hdmitx extcon rxsense*/ edev = extcon_dev_allocate(hdmi_cable); if (IS_ERR(edev)) { pr_info(SYS "failed to allocate extcon rxsense\n"); return; } - edev->dev.parent = dev; edev->name = "hdmitx_extcon_rxsense"; dev_set_name(&edev->dev, "hdmi_rxsense"); ret = extcon_dev_register(edev); if (ret < 0) { pr_info(SYS "failed to register extcon rxsense\n"); + extcon_dev_free(edev); return; } hdmitx_extcon_rxsense = edev; @@ -4306,17 +4578,16 @@ void hdmitx_extcon_register(struct platform_device *pdev, struct device *dev) pr_info(SYS "failed to allocate extcon hdcp\n"); return; } - edev->dev.parent = dev; edev->name = "hdmitx_extcon_hdcp"; dev_set_name(&edev->dev, "hdcp"); ret = extcon_dev_register(edev); if (ret < 0) { pr_info(SYS "failed to register extcon hdcp\n"); + extcon_dev_free(edev); return; } hdmitx_extcon_hdcp = edev; - } static void hdmitx_init_parameters(struct hdmitx_info *info) @@ -4421,6 +4692,7 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev) #ifdef CONFIG_OF if (pdev->dev.of_node) { + int dongle_mode = 0; memset(&hdmitx_device.config_data, 0, sizeof(struct hdmi_config_platform_data)); /* Get ic type information */ @@ -4432,6 +4704,14 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev) pr_info(SYS "hdmitx_device.chip_type : %d\n", hdmitx_device.chip_type); + /* Get dongle_mode information */ + ret = of_property_read_u32(pdev->dev.of_node, "dongle_mode", + &dongle_mode); + hdmitx_device.dongle_mode = !!dongle_mode; + if (!ret) + pr_info(SYS "hdmitx_device.dongle_mode: %d\n", + hdmitx_device.dongle_mode); + ret = of_property_read_u32(pdev->dev.of_node, "repeater_tx", &val); if (!ret) @@ -4440,6 +4720,11 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev) hdmitx_device.topo_info = kzalloc( sizeof(*hdmitx_device.topo_info), GFP_KERNEL); + ret = of_property_read_u32(pdev->dev.of_node, + "cedst_en", &val); + if (!ret) + hdmitx_device.cedst_en = !!val; + /* Get vendor information */ ret = of_property_read_u32(pdev->dev.of_node, "vend-data", &val); @@ -4514,6 +4799,7 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev) __func__); return -ENXIO; } + pr_info(SYS "hpd irq = %d\n", hdmitx_device.irq_hpd); return ret; @@ -4639,6 +4925,8 @@ static int amhdmitx_probe(struct platform_device *pdev) ret = device_create_file(dev, &dev_attr_frac_rate_policy); ret = device_create_file(dev, &dev_attr_sspll); ret = device_create_file(dev, &dev_attr_rxsense_policy); + ret = device_create_file(dev, &dev_attr_cedst_policy); + ret = device_create_file(dev, &dev_attr_cedst_count); ret = device_create_file(dev, &dev_attr_hdcp_clkdis); ret = device_create_file(dev, &dev_attr_hdcp_pwr); ret = device_create_file(dev, &dev_attr_hdcp_ksv_info); @@ -4664,6 +4952,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 if (suspend_hdmiphy) @@ -4736,6 +5025,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); @@ -4747,6 +5037,8 @@ static int amhdmitx_remove(struct platform_device *pdev) device_remove_file(dev, &dev_attr_frac_rate_policy); device_remove_file(dev, &dev_attr_sspll); device_remove_file(dev, &dev_attr_rxsense_policy); + device_remove_file(dev, &dev_attr_cedst_policy); + device_remove_file(dev, &dev_attr_cedst_count); device_remove_file(dev, &dev_attr_hdcp_pwr); device_remove_file(dev, &dev_attr_div40); device_remove_file(dev, &dev_attr_hdcp_repeater); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c index afb8f5d88e47..54b21c68e549 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c @@ -25,3 +25,74 @@ void scdc_config(struct hdmitx_dev *hdev) /* TMDS 1/40 & Scramble */ scdc_wr_sink(TMDS_CFG, hdev->para->tmds_clk_div40 ? 0x3 : 0); } + +/* update CED, 10.4.1.8 */ +static int scdc_ced_cnt(struct hdmitx_dev *hdev) +{ + struct ced_cnt *ced = &hdev->ced_cnt; + u8 raw[7]; + u8 chksum; + int i; + + memset(raw, 0, sizeof(raw)); + memset(ced, 0, sizeof(struct ced_cnt)); + + chksum = 0; + for (i = 0; i < 7; i++) { + scdc_rd_sink(ERR_DET_0_L + i, &raw[i]); + chksum += raw[i]; + } + + ced->ch0_cnt = raw[0] + ((raw[1] & 0x7f) << 8); + ced->ch0_valid = (raw[1] >> 7) & 0x1; + ced->ch1_cnt = raw[2] + ((raw[3] & 0x7f) << 8); + ced->ch1_valid = (raw[3] >> 7) & 0x1; + ced->ch2_cnt = raw[4] + ((raw[5] & 0x7f) << 8); + ced->ch2_valid = (raw[5] >> 7) & 0x1; + + /* Do checksum */ + if (chksum != 0) + pr_info("ced check sum error\n"); + if (ced->ch0_cnt) + pr_info("ced: ch0_cnt = %d %s\n", ced->ch0_cnt, + ced->ch0_valid ? "" : "unvalid"); + if (ced->ch1_cnt) + pr_info("ced: ch1_cnt = %d %s\n", ced->ch1_cnt, + ced->ch1_valid ? "" : "unvalid"); + if (ced->ch2_cnt) + pr_info("ced: ch2_cnt = %d %s\n", ced->ch2_cnt, + ced->ch2_valid ? "" : "unvalid"); + + return chksum != 0; +} + +/* update scdc status flags, 10.4.1.7 */ +/* ignore STATUS_FLAGS_1, all bits are RSVD */ +int scdc_status_flags(struct hdmitx_dev *hdev) +{ + u8 st = 0; + u8 locked_st = 0; + + scdc_rd_sink(UPDATE_0, &st); + if (st & STATUS_UPDATE) { + scdc_rd_sink(STATUS_FLAGS_0, &locked_st); + hdev->chlocked_st.clock_detected = locked_st & (1 << 0); + hdev->chlocked_st.ch0_locked = !!(locked_st & (1 << 1)); + hdev->chlocked_st.ch1_locked = !!(locked_st & (2 << 1)); + hdev->chlocked_st.ch2_locked = !!(locked_st & (3 << 1)); + } + if (st & CED_UPDATE) + scdc_ced_cnt(hdev); + if (st & (STATUS_UPDATE | CED_UPDATE)) + scdc_wr_sink(UPDATE_0, st & (STATUS_UPDATE | CED_UPDATE)); + if (!hdev->chlocked_st.clock_detected) + pr_info("ced: clock undetected\n"); + if (!hdev->chlocked_st.ch0_locked) + pr_info("ced: ch0 unlocked\n"); + if (!hdev->chlocked_st.ch1_locked) + pr_info("ced: ch1 unlocked\n"); + if (!hdev->chlocked_st.ch2_locked) + pr_info("ced: ch2 unlocked\n"); + + return st & (STATUS_UPDATE | CED_UPDATE); +} 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 2362064fdd5d..d5572d1d0885 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 @@ -882,12 +882,12 @@ static void hdmi_tx_construct_avi_packet( *************************************/ /* - * HDMI Identifier = 0x000c03 + * HDMI Identifier = HDMI_IEEEOUI 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_IEEEOUI) return 1; else return 0; @@ -994,6 +994,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; } } @@ -1025,9 +1048,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_IEEEOUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEEOUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEEOUI); VEN_DB[3] = 0x00; /* 4k x 2k Spec P156 */ if (VideoCode == HDMI_4k2k_30) { @@ -1061,9 +1084,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_IEEEOUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEEOUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEEOUI); VEN_DB[3] = 0x40; VEN_DB[4] = type<<4; VEN_DB[5] = param<<4; @@ -1101,3 +1124,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_IEEEOUI; + 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_IEEEOUI; + 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/enc_cfg_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c index 1aa8fe1c88a7..a482425b7765 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c @@ -61,8 +61,8 @@ static const struct reg_s tvregs_720p[] = { {P_ENCP_VIDEO_VSPULS_ELINE, 8}, {P_ENCP_VIDEO_HAVON_BEGIN, 260}, {P_ENCP_VIDEO_HAVON_END, 1539}, - {P_ENCP_VIDEO_VAVON_BLINE, 15}, - {P_ENCP_VIDEO_VAVON_ELINE, 744}, + {P_ENCP_VIDEO_VAVON_BLINE, 29}, + {P_ENCP_VIDEO_VAVON_ELINE, 749}, {P_ENCP_VIDEO_HSO_BEGIN, 0}, {P_ENCP_VIDEO_HSO_END, 168}, {P_ENCP_VIDEO_VSO_BEGIN, 168}, @@ -70,7 +70,6 @@ static const struct reg_s tvregs_720p[] = { {P_ENCP_VIDEO_VSO_BLINE, 0}, {P_ENCP_VIDEO_VSO_ELINE, 5}, {P_ENCP_VIDEO_MAX_LNCNT, 749}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -105,7 +104,6 @@ static const struct reg_s tvregs_720p_50hz[] = { {P_ENCP_VIDEO_MODE_ADV, 0x0018}, {P_ENCP_VIDEO_SYNC_MODE, 0x407}, {P_ENCP_VIDEO_YC_DLY, 0}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -136,7 +134,6 @@ static const struct reg_s tvregs_480i[] = { {P_ENCI_VFIFO2VD_LINE_TOP_END, 0x102,}, {P_ENCI_VFIFO2VD_LINE_BOT_START, 0x13,}, {P_ENCI_VFIFO2VD_LINE_BOT_END, 0x103,}, - {P_ENCP_VIDEO_EN, 0}, {P_ENCI_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -176,7 +173,6 @@ static const struct reg_s tvregs_480p[] = { {P_ENCP_DACSEL_0, 0x3102}, {P_ENCP_DACSEL_1, 0x0054}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -211,7 +207,6 @@ static const struct reg_s tvregs_576i[] = { {P_ENCI_VFIFO2VD_LINE_TOP_END, 0x0136}, {P_ENCI_VFIFO2VD_LINE_BOT_START, 0x0017}, {P_ENCI_VFIFO2VD_LINE_BOT_END, 0x0137}, - {P_ENCP_VIDEO_EN, 0}, {P_ENCI_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -249,7 +244,6 @@ static const struct reg_s tvregs_576p[] = { {P_ENCP_VIDEO_SY_VAL, 8}, {P_ENCP_VIDEO_SY2_VAL, 0x1d8}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -288,7 +282,6 @@ static const struct reg_s tvregs_1080i[] = { {P_ENCP_VIDEO_MODE_ADV, 0x0018}, {P_ENCP_VIDEO_SYNC_MODE, 0x207}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -323,7 +316,6 @@ static const struct reg_s tvregs_1080i_50hz[] = { {P_ENCP_VIDEO_MODE_ADV, 0x0018}, {P_ENCP_VIDEO_SYNC_MODE, 0x7}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -346,8 +338,8 @@ static const struct reg_s tvregs_1080p[] = { {P_ENCP_VIDEO_VSPULS_ELINE, 4}, {P_ENCP_VIDEO_HAVON_BEGIN, 148}, {P_ENCP_VIDEO_HAVON_END, 2067}, - {P_ENCP_VIDEO_VAVON_BLINE, 41}, - {P_ENCP_VIDEO_VAVON_ELINE, 1120}, + {P_ENCP_VIDEO_VAVON_BLINE, 42}, + {P_ENCP_VIDEO_VAVON_ELINE, 1121}, {P_ENCP_VIDEO_HSO_BEGIN, 44}, {P_ENCP_VIDEO_HSO_END, 2156}, {P_ENCP_VIDEO_VSO_BEGIN, 2100}, @@ -357,41 +349,6 @@ static const struct reg_s tvregs_1080p[] = { {P_ENCP_VIDEO_MAX_LNCNT, 1124}, {P_VENC_VIDEO_PROG_MODE, 0x100}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, - {MREG_END_MARKER, 0}, -}; - -static const struct reg_s tvregs_1080p_30hz[] = { - {P_ENCP_VIDEO_EN, 0}, - {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_FILT_CTRL, 0x1052}, - {P_VENC_DVI_SETTING, 0x0001}, - {P_ENCP_VIDEO_MODE, 0x4040}, - {P_ENCP_VIDEO_MODE_ADV, 0x0018}, - {P_ENCP_VIDEO_YFP1_HTIME, 140}, - {P_ENCP_VIDEO_YFP2_HTIME, 2060}, - {P_ENCP_VIDEO_MAX_PXCNT, 2199}, - {P_ENCP_VIDEO_HSPULS_BEGIN, 2156}, - {P_ENCP_VIDEO_HSPULS_END, 44}, - {P_ENCP_VIDEO_HSPULS_SWITCH, 44}, - {P_ENCP_VIDEO_VSPULS_BEGIN, 140}, - {P_ENCP_VIDEO_VSPULS_END, 2059}, - {P_ENCP_VIDEO_VSPULS_BLINE, 0}, - {P_ENCP_VIDEO_VSPULS_ELINE, 4}, - {P_ENCP_VIDEO_HAVON_BEGIN, 148}, - {P_ENCP_VIDEO_HAVON_END, 2067}, - {P_ENCP_VIDEO_VAVON_BLINE, 41}, - {P_ENCP_VIDEO_VAVON_ELINE, 1120}, - {P_ENCP_VIDEO_HSO_BEGIN, 44}, - {P_ENCP_VIDEO_HSO_END, 2156}, - {P_ENCP_VIDEO_VSO_BEGIN, 2100}, - {P_ENCP_VIDEO_VSO_END, 2164}, - {P_ENCP_VIDEO_VSO_BLINE, 0}, - {P_ENCP_VIDEO_VSO_ELINE, 5}, - {P_ENCP_VIDEO_MAX_LNCNT, 1124}, - {P_VENC_VIDEO_PROG_MODE, 0x100}, - {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -429,7 +386,6 @@ static const struct reg_s tvregs_1080p_50hz[] = { {P_ENCP_VIDEO_YC_DLY, 0}, {P_ENCP_VIDEO_RGB_CTRL, 2}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -468,7 +424,6 @@ static const struct reg_s tvregs_1080p_24hz[] = { {P_ENCP_VIDEO_YC_DLY, 0}, {P_ENCP_VIDEO_RGB_CTRL, 2}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -499,7 +454,6 @@ static const struct reg_s tvregs_4k2k_30hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 53}, {P_ENCP_VIDEO_MAX_LNCNT, 2249}, {P_ENCP_VIDEO_FILT_CTRL, 0x1000}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -531,7 +485,6 @@ static const struct reg_s tvregs_4k2k_25hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 53}, {P_ENCP_VIDEO_MAX_LNCNT, 2249}, {P_ENCP_VIDEO_FILT_CTRL, 0x1000}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -563,7 +516,6 @@ static const struct reg_s tvregs_4k2k_24hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 53}, {P_ENCP_VIDEO_MAX_LNCNT, 2249}, {P_ENCP_VIDEO_FILT_CTRL, 0x1000}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -595,7 +547,6 @@ static const struct reg_s tvregs_4k2k_smpte[] = { {P_ENCP_VIDEO_VSO_ELINE, 53}, {P_ENCP_VIDEO_MAX_LNCNT, 2249}, {P_ENCP_VIDEO_FILT_CTRL, 0x1000}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -617,7 +568,6 @@ static const struct reg_s tvregs_4k2k_smpte_25hz[] = { {P_ENCP_VIDEO_VSO_END, 0x32,}, {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, {P_ENCP_VIDEO_VSO_ELINE, 0xA,}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -639,7 +589,6 @@ static const struct reg_s tvregs_4k2k_smpte_30hz[] = { {P_ENCP_VIDEO_VSO_END, 0x32,}, {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, {P_ENCP_VIDEO_VSO_ELINE, 0xA,}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -661,7 +610,6 @@ static const struct reg_s tvregs_4k2k_smpte_50hz[] = { {P_ENCP_VIDEO_VSO_END, 0x32,}, {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, {P_ENCP_VIDEO_VSO_ELINE, 0xA,}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -683,7 +631,6 @@ static const struct reg_s tvregs_4k2k_smpte_60hz[] = { {P_ENCP_VIDEO_VSO_END, 0x32,}, {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, {P_ENCP_VIDEO_VSO_ELINE, 0xA,}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -723,7 +670,6 @@ static const struct reg_s tvregs_2560x1080p50hz[] = { {P_ENCP_VIDEO_RGB_CTRL, 2}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -762,7 +708,6 @@ static const struct reg_s tvregs_2560x1080p60hz[] = { {P_ENCP_VIDEO_RGB_CTRL, 2}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -785,7 +730,6 @@ static const struct reg_s tvregs_vesa_640x480p60hz[] = { {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, {P_ENCP_VIDEO_VSO_ELINE, 0x2,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -809,7 +753,6 @@ static const struct reg_s tvregs_vesa_800x600p60hz[] = { {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, {P_ENCP_VIDEO_VSO_ELINE, 0x4,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -833,7 +776,6 @@ static const struct reg_s tvregs_vesa_800x480p60hz[] = { {P_ENCP_VIDEO_VSO_BLINE, 0x0}, {P_ENCP_VIDEO_VSO_ELINE, 0x7}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -857,7 +799,6 @@ static const struct reg_s tvregs_vesa_852x480p60hz[] = { {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, {P_ENCP_VIDEO_VSO_ELINE, 0x2,},/*2//ver sync time*/ {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -881,7 +822,6 @@ static const struct reg_s tvregs_vesa_854x480p60hz[] = { {P_ENCP_VIDEO_VSO_BLINE, 0x0,}, {P_ENCP_VIDEO_VSO_ELINE, 0x2,},/*2//ver sync time*/ {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -907,7 +847,6 @@ static const struct reg_s tvregs_vesa_1024x600p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x6,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -933,7 +872,6 @@ static const struct reg_s tvregs_vesa_1024x768p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x6,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -959,7 +897,6 @@ static const struct reg_s tvregs_vesa_1152x864p75hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x3,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -987,7 +924,6 @@ static const struct reg_s tvregs_vesa_1280x600p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} #endif }; @@ -1014,7 +950,6 @@ static const struct reg_s tvregs_vesa_1280x768p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; @@ -1040,7 +975,6 @@ static const struct reg_s tvregs_vesa_1280x800p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; @@ -1066,7 +1000,6 @@ static const struct reg_s tvregs_vesa_1280x960p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; @@ -1092,7 +1025,6 @@ static const struct reg_s tvregs_vesa_1280x1024p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; @@ -1118,7 +1050,6 @@ static const struct reg_s tvregs_vesa_1360x768p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x6,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -1145,7 +1076,6 @@ static const struct reg_s tvregs_vesa_1366x768p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x3,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -1172,7 +1102,6 @@ static const struct reg_s tvregs_vesa_1400x1050p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x4,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -1199,7 +1128,6 @@ static const struct reg_s tvregs_vesa_1440x900p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x6,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -1226,7 +1154,6 @@ static const struct reg_s tvregs_vesa_1440x2560p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x4,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -1253,7 +1180,6 @@ static const struct reg_s tvregs_vesa_1600x900p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x3,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -1280,7 +1206,6 @@ static const struct reg_s tvregs_vesa_1600x1200p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x3,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -1306,7 +1231,6 @@ static const struct reg_s tvregs_vesa_1680x1050p60hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x6,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1,}, {P_ENCI_VIDEO_EN, 0,}, {MREG_END_MARKER, 0} }; @@ -1333,7 +1257,6 @@ static const struct reg_s tvregs_vesa_1920x1200p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; @@ -1357,7 +1280,6 @@ static const struct reg_s tvregs_vesa_2160x1200p90hz[] = { {P_ENCP_VIDEO_VSO_ELINE, 0x3,}, {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, - {P_ENCP_VIDEO_EN, 1}, {P_ENCI_VIDEO_EN, 0}, {MREG_END_MARKER, 0}, }; @@ -1384,7 +1306,6 @@ static const struct reg_s tvregs_vesa_2560x1600p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; @@ -1411,7 +1332,6 @@ static const struct reg_s tvregs_vesa_2560x1080p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; @@ -1437,7 +1357,6 @@ static const struct reg_s tvregs_vesa_2560x1440p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; @@ -1463,7 +1382,6 @@ static const struct reg_s tvregs_vesa_3440x1440p60hz[] = { {P_VPU_VIU_VENC_MUX_CTRL, 0xA}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0} }; #endif @@ -1490,7 +1408,7 @@ static struct vic_tvregs_set tvregsTab[] = { {HDMI_1920x1080i50_16x9, tvregs_1080i_50hz}, {HDMI_1920x1080p50_16x9, tvregs_1080p_50hz}, {HDMI_1920x1080p25_16x9, tvregs_1080p_50hz}, - {HDMI_1920x1080p30_16x9, tvregs_1080p_30hz}, + {HDMI_1920x1080p30_16x9, tvregs_1080p}, {HDMI_1920x1080p24_16x9, tvregs_1080p_24hz}, {HDMI_3840x2160p30_16x9, tvregs_4k2k_30hz}, {HDMI_3840x2160p25_16x9, tvregs_4k2k_25hz}, @@ -1573,7 +1491,6 @@ static const struct reg_s tvregs_3dfp_1080p60[] = { {P_ENCP_DE_V_END_ODD, 0x0,}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -1613,7 +1530,6 @@ static const struct reg_s tvregs_3dfp_1080p24[] = { {P_ENCP_DE_V_END_ODD, 0x0,}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -1653,7 +1569,6 @@ static const struct reg_s tvregs_3dfp_1080p50[] = { {P_ENCP_DE_V_END_ODD, 0x0,}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -1693,7 +1608,6 @@ static const struct reg_s tvregs_3dfp_720p50[] = { {P_ENCP_DE_V_END_ODD, 0x0,}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 0}, }; @@ -1733,7 +1647,6 @@ static const struct reg_s tvregs_3dfp_720p60[] = { {P_ENCP_DE_V_END_ODD, 0x0,}, {P_ENCI_VIDEO_EN, 0}, - {P_ENCP_VIDEO_EN, 1}, {MREG_END_MARKER, 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 2eebb0d1a1ca..c0f9cd821d0d 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 @@ -47,6 +47,7 @@ #include "hw_clk.h" #include #include "checksha.h" +#include static void mode420_half_horizontal_para(void); static void hdmi_phy_suspend(void); @@ -68,6 +69,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); @@ -86,6 +89,7 @@ static int hdmitx_cntl_config(struct hdmitx_dev *hdev, unsigned int cmd, unsigned int argv); static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd, unsigned int argv); +static enum hdmi_vic get_vic_from_pkt(void); #define EDID_RAM_ADDR_SIZE (8) @@ -160,6 +164,7 @@ int hdmitx_hpd_hw_op(enum hpd_op cmd) case MESON_CPU_ID_GXM: return hdmitx_hpd_hw_op_gxl(cmd); case MESON_CPU_ID_TXLX: + case MESON_CPU_ID_TM2: return hdmitx_hpd_hw_op_txlx(cmd); case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: @@ -198,6 +203,7 @@ int read_hpd_gpio(void) return 1; else #endif + case MESON_CPU_ID_TM2: return read_hpd_gpio_txlx(); default: break; @@ -222,6 +228,7 @@ int hdmitx_ddc_hw_op(enum ddc_op cmd) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: return hdmitx_ddc_hw_op_txlx(cmd); default: break; @@ -303,6 +310,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; @@ -446,6 +458,7 @@ static unsigned int hdmitx_get_format(void) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: ret = hdmitx_get_format_txlx(); break; case MESON_CPU_ID_GXBB: @@ -493,6 +506,7 @@ void hdmitx_sys_reset(void) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: hdmitx_sys_reset_txlx(); break; case MESON_CPU_ID_GXBB: @@ -527,6 +541,7 @@ static void hdmi_hwp_init(struct hdmitx_dev *hdev) /* enable CLK_TO_DIG */ hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL3, 0x3, 0, 2); if (hdmitx_uboot_already_display()) { + hdev->cur_VIC = get_vic_from_pkt(); hdev->ready = 1; /* Get uboot output color space from AVI */ switch (hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF0) & 0x3) { @@ -610,6 +625,11 @@ static void hdmi_hwi_init(struct hdmitx_dev *hdev) hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 6, 1); /* Enable tmds_clk to HDCP2.2 IP */ hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 5, 1); + /* Enable axi_clk */ + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 13, 1); + /* Enable axi_async_req_en_emp & axi_async_req_en_esm */ + hdmitx_set_reg_bits(HDMITX_TOP_AXI_ASYNC_CNTL0, 1, 0, 1); + hdmitx_set_reg_bits(HDMITX_TOP_AXI_ASYNC_CNTL0, 1, 16, 1); hdmitx_hpd_hw_op(HPD_INIT_DISABLE_PULLUP); hdmitx_hpd_hw_op(HPD_INIT_SET_FILTER); @@ -663,6 +683,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; @@ -681,6 +702,25 @@ void HDMITX_Meson_Init(struct hdmitx_dev *hdev) hdev->HWOp.CntlMisc(hdev, MISC_AVMUTE_OP, CLR_AVMUTE); } +static void hdmitx_phy_bandgap_en(struct hdmitx_dev *hdev) +{ + unsigned int val = 0; + switch (hdev->chip_type) { + case MESON_CPU_ID_TM2: + val = hd_read_reg(P_TM2_HHI_HDMI_PHY_CNTL0); + if (val == 0) + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL0, 0x0b4242); + break; + case MESON_CPU_ID_SM1: + val = hd_read_reg(P_HHI_HDMI_PHY_CNTL0); + if (val == 0) + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x0b4242); + break; + default: + break; + } +} + static irqreturn_t intr_handler(int irq, void *dev) { /* get interrupt status */ @@ -720,6 +760,8 @@ static irqreturn_t intr_handler(int irq, void *dev) hdev->hdmitx_event |= HDMI_TX_HPD_PLUGIN; hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT; hdev->rhpd_state = 1; + hdmitx_phy_bandgap_en(hdev); + earc_hdmitx_hpdst(1); queue_delayed_work(hdev->hdmi_wq, &hdev->work_hpd_plugin, HZ / 2); } @@ -728,6 +770,7 @@ static irqreturn_t intr_handler(int irq, void *dev) hdev->hdmitx_event |= HDMI_TX_HPD_PLUGOUT; hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGIN; hdev->rhpd_state = 0; + earc_hdmitx_hpdst(0); queue_delayed_work(hdev->hdmi_wq, &hdev->work_hpd_plugout, HZ / 50); } @@ -786,12 +829,9 @@ static void enc_vpu_bridge_reset(int mode) wr_clk = (hd_read_reg(P_VPU_HDMI_SETTING) & 0xf00) >> 8; if (mode) { - hd_write_reg(P_ENCP_VIDEO_EN, 0); hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 0, 2); hd_set_reg_bits(P_VPU_HDMI_SETTING, 0, 8, 4); mdelay(1); - hd_write_reg(P_ENCP_VIDEO_EN, 1); - mdelay(1); hd_set_reg_bits(P_VPU_HDMI_SETTING, wr_clk, 8, 4); mdelay(1); hd_set_reg_bits(P_VPU_HDMI_SETTING, 2, 0, 2); @@ -1140,7 +1180,6 @@ static void hdmi_tvenc4k2k_set(struct hdmitx_vidpara *param) (0 << 12) ); hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); - hd_write_reg(P_ENCP_VIDEO_EN, 1); } static void hdmi_tvenc480i_set(struct hdmitx_vidpara *param) @@ -1851,7 +1890,6 @@ static void hdmi_tvenc_set(struct hdmitx_vidpara *param) (0 << 12) ); hd_set_reg_bits(P_VPU_HDMI_SETTING, 1, 1, 1); - hd_write_reg(P_ENCP_VIDEO_EN, 1); /* Enable VENC */ break; case HDMI_480p60_16x9_rpt: case HDMI_576p50_16x9_rpt: @@ -1926,19 +1964,38 @@ static void set_phy_by_mode(unsigned int mode) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: switch (mode) { - case 1: /* 5.94/4.5/3.7Gbps */ - hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb65c4); + case HDMI_PHYPARA_6G: /* 5.94Gbps */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb76d4); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x0000080b); break; - case 2: /* 2.97Gbps */ - hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb6262); + case HDMI_PHYPARA_4p5G: /* 4.5Gbps*/ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb65d4); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); + hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x0000080b); + break; + case HDMI_PHYPARA_3p7G: /* 3.7Gbps */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb65c4); + if (hdev->dongle_mode) + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb5584); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); + hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x0000080b); + break; + case HDMI_PHYPARA_3G: /* 2.97Gbps */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb6272); + if (hdev->dongle_mode) + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb4262); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x00000003); break; - case 3: /* 1.485Gbps, and below */ + case HDMI_PHYPARA_270M: /* SD format, 480p/576p, 270Mbps */ + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb5252); + hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); + hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x00000003); + break; + case HDMI_PHYPARA_DEF: /* less than 2.97G */ default: - hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb4242); + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb4262); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x00000003); break; @@ -1946,17 +2003,20 @@ static void set_phy_by_mode(unsigned int mode) break; case MESON_CPU_ID_SM1: switch (mode) { - case 1: /* 5.94/4.5/3.7Gbps */ + case HDMI_PHYPARA_6G: /* 5.94/4.5/3.7Gbps */ + case HDMI_PHYPARA_4p5G: + case HDMI_PHYPARA_3p7G: hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb65c4); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x0000080b); break; - case 2: /* 2.97Gbps */ + case HDMI_PHYPARA_3G: /* 2.97Gbps */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb42a2); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x00000003); break; - case 3: /* 1.485Gbps, and below */ + case HDMI_PHYPARA_270M: /* 1.485Gbps, and below */ + case HDMI_PHYPARA_DEF: default: hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb4242); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); @@ -1964,20 +2024,46 @@ static void set_phy_by_mode(unsigned int mode) break; } break; + case MESON_CPU_ID_TM2: + switch (mode) { + case HDMI_PHYPARA_6G: /* 5.94/4.5/3.7Gbps */ + case HDMI_PHYPARA_4p5G: + case HDMI_PHYPARA_3p7G: + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL0, 0x33EB65c4); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL5, 0x0000080b); + break; + case HDMI_PHYPARA_3G: /* 2.97Gbps */ + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL0, 0x33eb42a5); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL5, 0x00000003); + break; + case HDMI_PHYPARA_270M: /* 1.485Gbps, and below */ + case HDMI_PHYPARA_DEF: + default: + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL0, 0x33eb4262); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL5, 0x00000003); + break; + } + break; case MESON_CPU_ID_M8B: case MESON_CPU_ID_GXBB: case MESON_CPU_ID_GXTVBB: /* other than GXL */ switch (mode) { - case 1: /* 5.94Gbps, 3.7125Gbsp */ + case HDMI_PHYPARA_6G: /* 5.94Gbps, 3.7125Gbsp */ + case HDMI_PHYPARA_4p5G: + case HDMI_PHYPARA_3p7G: hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33353245); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2100115b); break; - case 2: /* 2.97Gbps */ + case HDMI_PHYPARA_3G: /* 2.97Gbps */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33634283); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0xb000115b); break; - case 3: /* 1.485Gbps, and below */ + case HDMI_PHYPARA_270M: /* 1.485Gbps, and below */ + case HDMI_PHYPARA_DEF: default: hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33632122); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2000115b); @@ -1993,18 +2079,21 @@ static void set_phy_by_mode(unsigned int mode) case MESON_CPU_ID_TXHD: default: switch (mode) { - case 1: /* 5.94Gbps, 3.7125Gbsp */ + case HDMI_PHYPARA_6G: /* 5.94Gbps, 3.7125Gbsp */ + case HDMI_PHYPARA_4p5G: + case HDMI_PHYPARA_3p7G: hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x333d3282); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2136315b); break; - case 2: /* 2.97Gbps */ + case HDMI_PHYPARA_3G: /* 2.97Gbps */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33303382); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2036315b); break; - case 3: /* 1.485Gbps */ + case HDMI_PHYPARA_DEF: /* 1.485Gbps */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33303042); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2016315b); break; + case HDMI_PHYPARA_270M: default: /* 742.5Mbps, and below */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33604132); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x0016315b); @@ -2019,7 +2108,28 @@ static void hdmitx_set_phy(struct hdmitx_dev *hdev) if (!hdev) return; hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x0); + if (hdev->chip_type == MESON_CPU_ID_TM2) { +/* P_HHI_HDMI_PHY_CNTL1 bit[1]: enable clock bit[0]: soft reset */ +#define RESET_HDMI_PHY() \ +do { \ + hd_set_reg_bits(P_TM2_HHI_HDMI_PHY_CNTL1, 0xf, 0, 4); \ + mdelay(2); \ + hd_set_reg_bits(P_TM2_HHI_HDMI_PHY_CNTL1, 0xe, 0, 4); \ + mdelay(2); \ +} while (0) + + hd_set_reg_bits(P_TM2_HHI_HDMI_PHY_CNTL1, 0x0390, 16, 16); + hd_set_reg_bits(P_TM2_HHI_HDMI_PHY_CNTL1, 0x1, 17, 1); + hd_set_reg_bits(P_TM2_HHI_HDMI_PHY_CNTL1, 0x0, 17, 1); + hd_set_reg_bits(P_TM2_HHI_HDMI_PHY_CNTL1, 0x0, 0, 4); + msleep(20); + RESET_HDMI_PHY(); + RESET_HDMI_PHY(); + RESET_HDMI_PHY(); +#undef RESET_HDMI_PHY + + } else { /* P_HHI_HDMI_PHY_CNTL1 bit[1]: enable clock bit[0]: soft reset */ #define RESET_HDMI_PHY() \ do { \ @@ -2029,18 +2139,44 @@ do { \ mdelay(2); \ } while (0) - hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0390, 16, 16); - hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x1, 17, 1); - if (hdev->chip_type >= MESON_CPU_ID_GXL) - hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0, 17, 1); - hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0, 0, 4); - msleep(100); - RESET_HDMI_PHY(); - RESET_HDMI_PHY(); - RESET_HDMI_PHY(); + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0390, 16, 16); + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x1, 17, 1); + if (hdev->chip_type >= MESON_CPU_ID_GXL) + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0, 17, 1); + hd_set_reg_bits(P_HHI_HDMI_PHY_CNTL1, 0x0, 0, 4); + msleep(20); + RESET_HDMI_PHY(); + RESET_HDMI_PHY(); + RESET_HDMI_PHY(); #undef RESET_HDMI_PHY + } switch (hdev->cur_VIC) { + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + if (hdev->para->cs != COLORSPACE_YUV420) + set_phy_by_mode(HDMI_PHYPARA_6G); + else + if (hdev->para->cd == COLORDEPTH_36B) + set_phy_by_mode(HDMI_PHYPARA_4p5G); + else if (hdev->para->cd == COLORDEPTH_30B) + set_phy_by_mode(HDMI_PHYPARA_3p7G); + else + set_phy_by_mode(HDMI_PHYPARA_3G); + break; + case HDMI_3840x2160p50_16x9_Y420: + case HDMI_3840x2160p60_16x9_Y420: + case HDMI_4096x2160p50_256x135_Y420: + case HDMI_4096x2160p60_256x135_Y420: + if (hdev->para->cd == COLORDEPTH_36B) + set_phy_by_mode(HDMI_PHYPARA_4p5G); + else if (hdev->para->cd == COLORDEPTH_30B) + set_phy_by_mode(HDMI_PHYPARA_3p7G); + else + set_phy_by_mode(HDMI_PHYPARA_3G); + break; case HDMI_4k2k_24: case HDMI_4k2k_25: case HDMI_4k2k_30: @@ -2049,48 +2185,25 @@ do { \ case HDMI_4096x2160p30_256x135: if ((hdev->para->cs == COLORSPACE_YUV422) || (hdev->para->cd == COLORDEPTH_24B)) - set_phy_by_mode(2); + set_phy_by_mode(HDMI_PHYPARA_3G); else - set_phy_by_mode(1); + if (hdev->para->cd == COLORDEPTH_36B) + set_phy_by_mode(HDMI_PHYPARA_4p5G); + else if (hdev->para->cd == COLORDEPTH_30B) + set_phy_by_mode(HDMI_PHYPARA_3p7G); + else + set_phy_by_mode(HDMI_PHYPARA_3G); break; - case HDMI_3840x2160p50_16x9: - case HDMI_3840x2160p60_16x9: - case HDMI_4096x2160p50_256x135: - case HDMI_4096x2160p60_256x135: - if (hdev->para->cs == COLORSPACE_YUV420) - set_phy_by_mode(2); - else - set_phy_by_mode(1); - break; - case HDMI_3840x2160p50_16x9_Y420: - case HDMI_3840x2160p60_16x9_Y420: - case HDMI_4096x2160p50_256x135_Y420: - case HDMI_4096x2160p60_256x135_Y420: - if (hdev->para->cd == COLORDEPTH_24B) - set_phy_by_mode(2); - else - set_phy_by_mode(1); - break; - /* consider HPLL over 2Gbps */ - case HDMI_2560x1600p60_8x5: - case HDMI_2560x1440p60_16x9: - if (hdev->para->cd == COLORDEPTH_24B) - set_phy_by_mode(2); - else - set_phy_by_mode(1); + case HDMI_720x480p60_16x9: + case HDMI_720x576p50_16x9: + case HDMI_720x480i60_16x9: + case HDMI_720x576i50_16x9: + set_phy_by_mode(HDMI_PHYPARA_270M); break; case HDMI_1080p60: case HDMI_1080p50: - if (hdev->flag_3dfp) - set_phy_by_mode(2); - else - set_phy_by_mode(3); - break; default: - if (hdev->flag_3dfp) - set_phy_by_mode(3); - else - set_phy_by_mode(4); + set_phy_by_mode(HDMI_PHYPARA_DEF); break; } } @@ -2163,9 +2276,6 @@ static void hdmitx_set_scdc(struct hdmitx_dev *hdev) void hdmitx_set_enc_hw(struct hdmitx_dev *hdev) { - if (hdev->para->hdmitx_vinfo.viu_mux == VIU_MUX_ENCI) - hdmitx_set_vclk2_enci(hdev); - set_vmode_enc_hw(hdev); if (hdev->flag_3dfp) { @@ -2290,12 +2400,12 @@ static int hdmitx_set_dispmode(struct hdmitx_dev *hdev) hdmitx_set_enc_hw(hdev); - hdmitx_set_hw(hdev); - /* For 3D, enable phy by SystemControl at last step */ if ((!hdev->flag_3dfp) && (!hdev->flag_3dtb) && (!hdev->flag_3dss)) hdmitx_set_phy(hdev); + hdmitx_set_hw(hdev); + return 0; } @@ -2303,6 +2413,7 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) { int i; int pkt_data_len = 0; + unsigned int IEEECode = 0; switch (type) { case HDMI_PACKET_AVI: @@ -2311,6 +2422,12 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) if ((!DB) || (!HB)) { hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 0, 3, 1); hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 0x0); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID0, 0x00); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID1, 0x00); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID2, 0x00); + for (i = 0; i < 24; i++) + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD0 + i, + 0x00); return; } hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID0, DB[0]); @@ -2318,11 +2435,14 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID2, DB[2]); hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD0, DB[3]); hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, HB[2]); - if (DB[3] == 0x20) { /* set HDMI VIC */ + IEEECode = DB[0] | DB[1] << 8 | DB[2] << 16; + if ((IEEECode == HDMI_IEEEOUI) && (DB[3] == 0x20)) { + /* set HDMI VIC */ hdmitx_wr_reg(HDMITX_DWC_FC_AVIVID, 0); hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1, DB[4]); } - if (DB[3] == 0x40) { /* 3D VSI */ + if ((IEEECode == HDMI_IEEEOUI) && (DB[3] == 0x40)) { + /* 3D VSI */ hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1, DB[4]); hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD2, DB[5]); if ((DB[4] >> 4) == T3D_FRAME_PACKING) @@ -2330,7 +2450,8 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) else hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 6); } - if (HB[2] == 0x1b) {/*set dolby vsif data information*/ + if ((IEEECode == DOVI_IEEEOUI) && (HB[2] == 0x1b)) { + /*set dolby vsif data information*/ hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1, DB[4]); hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD2, DB[5]); hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD3, DB[6]); @@ -2338,7 +2459,7 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD5, DB[8]); } /*set hdr 10+ vsif data information*/ - if ((DB[0] == 0x8b) && (DB[1] == 0x84) && (DB[2] == 0x90)) { + if (IEEECode == HDR10PLUS_IEEEOUI) { for (i = 0; i < 23; i++) hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD1 + i, DB[4 + i]); @@ -2382,6 +2503,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) @@ -2842,6 +2997,7 @@ static int hdmitx_cntl(struct hdmitx_dev *hdev, unsigned int cmd, case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 1, 29, 1); udelay(50); hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0, 28, 1); @@ -4210,7 +4366,7 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) pr_info("topo: %d\n", hdmitx_hdcp_opr(0xe)); return; } else if (strncmp(tmpbuf, "dumphdmireg", 11) == 0) { - unsigned char reg_val = 0; + unsigned int reg_val = 0; unsigned int reg_adr = 0; #define DUMP_HDMITX_SECTION(a, b) \ @@ -4235,8 +4391,10 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) HDMITX_TOP_SEC_SCRATCH); DUMP_HDMITX_SECTION(HDMITX_DWC_DESIGN_ID, HDMITX_DWC_A_KSVMEMCTRL); +#if 0 DUMP_HDMITX_HDCP_SECTION(HDMITX_DWC_HDCP_BSTATUS_0, HDMITX_DWC_HDCP_REVOC_LIST_END); +#endif DUMP_HDMITX_HDCP_SECTION(HDMITX_DWC_HDCPREG_BKSV0, HDMITX_DWC_HDCPREG_BKSV4); DUMP_HDMITX_SECTION(HDMITX_DWC_HDCPREG_ANCONF, @@ -4346,6 +4504,28 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) (P_HHI_HDMI_PHY_STATUS)); } break; + case MESON_CPU_ID_TM2: + for (i = 0; i < 4; i++) { + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL1, + 0x0390000f); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL1, + 0x0390000e); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL1, + 0x03904002); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL4, + 0x0001efff | (i << 20)); + hd_write_reg(P_TM2_HHI_HDMI_PHY_CNTL1, + 0xef904002); + mdelay(10); + if (i > 0) + pr_info("prbs D[%d]:%x\n", i - 1, + hd_read_reg + (P_TM2_HHI_HDMI_PHY_STATUS)); + else + pr_info("prbs clk :%x\n", hd_read_reg + (P_TM2_HHI_HDMI_PHY_STATUS)); + } + break; default: break; } @@ -4644,9 +4824,6 @@ static void hdcptx_events_handle(unsigned long arg) pr_info("hdcp14: instat: 0x%x\n", st_flag); } - if (st_flag & (1 << 6)) - hdmitx_set_reg_bits(HDMITX_DWC_A_HDCPCFG1, 1, 1, 1); - if (st_flag & (1 << 7)) { hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, 1 << 7); hdmitx_hdcp_opr(3); @@ -4805,6 +4982,7 @@ static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd, break; case DDC_HDCP_MUX_INIT: if (argv == 2) { + hd_write_reg(P_HHI_HDCP22_CLK_CNTL, 0x01000100); hdmitx_ddc_hw_op(DDC_MUX_DDC); hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, 1, 6, 1); udelay(5); @@ -5013,6 +5191,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; @@ -5070,10 +5270,18 @@ static int hdmitx_tmds_rxsense(void) hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0); break; } - + if (!(hdev->HWOp.CntlMisc(hdev, MISC_HPD_GPI_ST, 0))) + return 0; return ret; } +/*Check from SCDC Status_Flags_0/1 */ +/* 0 means TMDS ok */ +static int hdmitx_tmds_cedst(struct hdmitx_dev *hdev) +{ + return scdc_status_flags(hdev); +} + static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd, unsigned int argv) { @@ -5093,6 +5301,9 @@ static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd, return hdmitx_hpd_hw_op(argv); case MISC_HPD_GPI_ST: return hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO); + case MISC_TRIGGER_HPD: + hdmitx_wr_reg(HDMITX_TOP_INTR_STAT, 1 << 1); + return 0; case MISC_HPLL_FAKE: hdmitx_set_fake_vic(hdev); break; @@ -5104,6 +5315,8 @@ static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd, break; case MISC_TMDS_RXSENSE: return hdmitx_tmds_rxsense(); + case MISC_TMDS_CEDST: + return hdmitx_tmds_cedst(hdev); case MISC_ESM_RESET: if (hdev->hdcp_hpd_stick == 1) { pr_info(HW "hdcp: stick mode\n"); @@ -5983,7 +6196,6 @@ static void config_hdmi20_tx(enum hdmi_vic vic, /* Reset pulse */ hdmitx_rd_check_reg(HDMITX_DWC_MC_LOCKONCLOCK, 0xff, 0x9f); - hd_write_reg(P_ENCP_VIDEO_EN, 0); hdmitx_wr_reg(HDMITX_DWC_MC_CLKDIS, 0xdf); hdmitx_wr_reg(HDMITX_DWC_MC_SWRSTZREQ, 0); mdelay(10); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c index 3a74db3e4dff..bd99c2a42330 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c @@ -67,18 +67,41 @@ void hdmitx_set_sys_clk(struct hdmitx_dev *hdev, unsigned char flag) if (flag&2) { hdmitx_set_top_pclk(hdev); - hdmitx_set_vclk2_encp(hdev); + + hd_write_reg(P_HHI_GCLK_OTHER, + hd_read_reg(P_HHI_GCLK_OTHER)|(1<<17)); } } -void hdmitx_set_vclk2_encp(struct hdmitx_dev *hdev) +static void hdmitx_disable_encp_clk(struct hdmitx_dev *hdev) { - hd_write_reg(P_HHI_GCLK_OTHER, - hd_read_reg(P_HHI_GCLK_OTHER)|(1<<17)); + hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 0, 2, 1); + +#ifdef CONFIG_AMLOGIC_VPU + switch_vpu_clk_gate_vmod(VPU_VENCP, VPU_CLK_GATE_OFF); + switch_vpu_mem_pd_vmod(VPU_VENCP, VPU_MEM_POWER_DOWN); +#endif } -void hdmitx_disable_vclk2_enci(struct hdmitx_dev *hdev) +static void hdmitx_enable_encp_clk(struct hdmitx_dev *hdev) { +#ifdef CONFIG_AMLOGIC_VPU + switch_vpu_clk_gate_vmod(VPU_VENCP, VPU_CLK_GATE_ON); + switch_vpu_mem_pd_vmod(VPU_VENCP, VPU_MEM_POWER_ON); +#endif + + hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 1, 2, 1); +} + +static void hdmitx_disable_enci_clk(struct hdmitx_dev *hdev) +{ + hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 0, 0, 1); + +#ifdef CONFIG_AMLOGIC_VPU + switch_vpu_clk_gate_vmod(VPU_VENCI, VPU_CLK_GATE_OFF); + switch_vpu_mem_pd_vmod(VPU_VENCI, VPU_MEM_POWER_DOWN); +#endif + if (hdev->hdmitx_clk_tree.venci_top_gate) clk_disable_unprepare(hdev->hdmitx_clk_tree.venci_top_gate); @@ -87,15 +110,9 @@ void hdmitx_disable_vclk2_enci(struct hdmitx_dev *hdev) if (hdev->hdmitx_clk_tree.venci_1_gate) clk_disable_unprepare(hdev->hdmitx_clk_tree.venci_1_gate); - -#ifdef CONFIG_AMLOGIC_VPU - switch_vpu_clk_gate_vmod(VPU_VENCI, VPU_CLK_GATE_OFF); - switch_vpu_mem_pd_vmod(VPU_VENCI, VPU_MEM_POWER_DOWN); -#endif - } -void hdmitx_set_vclk2_enci(struct hdmitx_dev *hdev) +static void hdmitx_enable_enci_clk(struct hdmitx_dev *hdev) { if (hdev->hdmitx_clk_tree.venci_top_gate) clk_prepare_enable(hdev->hdmitx_clk_tree.venci_top_gate); @@ -111,6 +128,12 @@ void hdmitx_set_vclk2_enci(struct hdmitx_dev *hdev) switch_vpu_mem_pd_vmod(VPU_VENCI, VPU_MEM_POWER_ON); #endif + hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 1, 0, 1); +} + +static void hdmitx_disable_tx_pixel_clk(struct hdmitx_dev *hdev) +{ + hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 0, 5, 1); } void hdmitx_set_cts_sys_clk(struct hdmitx_dev *hdev) @@ -166,6 +189,7 @@ void hdmitx_set_cts_hdcp22_clk(struct hdmitx_dev *hdev) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: default: hd_write_reg(P_HHI_HDCP22_CLK_CNTL, 0x01000100); break; @@ -399,7 +423,7 @@ static void set_gxtvbb_hpll_clk_out(unsigned int frac_rate, unsigned int clk) hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0x4, 28, 3); WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL); pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL)); - hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4e00, 0, 16); + /* hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 0x4e00, 0, 16); */ break; case 4324320: hd_write_reg(P_HHI_HDMI_PLL_CNTL, 0x5800025a); @@ -443,6 +467,7 @@ static void set_hpll_clk_out(unsigned int clk) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: set_g12a_hpll_clk_out(frac_rate, clk); break; default: @@ -461,6 +486,7 @@ static void set_hpll_sspll(enum hdmi_vic vic) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: set_hpll_sspll_g12a(vic); break; case MESON_CPU_ID_GXBB: @@ -507,6 +533,7 @@ static void set_hpll_od1(unsigned int div) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: set_hpll_od1_g12a(div); break; default: @@ -546,6 +573,7 @@ static void set_hpll_od2(unsigned int div) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: set_hpll_od2_g12a(div); break; default: @@ -587,6 +615,11 @@ static void set_hpll_od3(unsigned int div) case MESON_CPU_ID_SM1: set_hpll_od3_g12a(div); break; + case MESON_CPU_ID_TM2: + set_hpll_od3_g12a(div); + /* new added in TM2 */ + hd_set_reg_bits(P_HHI_LVDS_TX_PHY_CNTL1, 1, 29, 1); + break; default: set_hpll_od3_gxl(div); break; @@ -720,7 +753,6 @@ static void set_encp_div(unsigned int div) if (div == -1) return; hd_set_reg_bits(P_HHI_VID_CLK_DIV, div, 24, 4); - hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 1, 2, 1); hd_set_reg_bits(P_HHI_VID_CLK_CNTL, 1, 19, 1); } @@ -730,7 +762,6 @@ static void set_enci_div(unsigned int div) if (div == -1) return; hd_set_reg_bits(P_HHI_VID_CLK_DIV, div, 28, 4); - hd_set_reg_bits(P_HHI_VID_CLK_CNTL2, 1, 0, 1); hd_set_reg_bits(P_HHI_VID_CLK_CNTL, 1, 19, 1); } @@ -789,10 +820,6 @@ static struct hw_enc_clk_val_group setting_enc_clk_val_24[] = { HDMI_3840x2160p50_16x9_Y420, HDMI_VIC_END}, 5940000, 2, 1, 1, VID_PLL_DIV_5, 1, 2, 1, -1}, - {{HDMI_CUSTOMBUILT, - HDMI_VIC_END}, - /* default 1080p60hz */ - 5940000, 4, 1, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, {{HDMI_VIC_FAKE, HDMI_VIC_END}, 3450000, 1, 2, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, @@ -856,6 +883,10 @@ static struct hw_enc_clk_val_group setting_enc_clk_val_24[] = { {{HDMIV_2560x1600p60hz, HDMI_VIC_END}, 3485000, 1, 1, 1, VID_PLL_DIV_5, 2, 1, 1, -1}, + {{HDMI_CUSTOMBUILT, + HDMI_VIC_END}, + /* default 1080p60hz */ + 5940000, 4, 1, 2, VID_PLL_DIV_5, 1, 1, 1, -1}, }; /* For colordepth 10bits */ @@ -1099,8 +1130,14 @@ next: pr_info("j = %d vid_clk_div = %d\n", j, p_enc[j].vid_clk_div); set_vid_clk_div(p_enc[j].vid_clk_div); set_hdmi_tx_pixel_div(p_enc[j].hdmi_tx_pixel_div); - set_encp_div(p_enc[j].encp_div); - set_enci_div(p_enc[j].enci_div); + + if (hdev->para->hdmitx_vinfo.viu_mux == VIU_MUX_ENCI) { + set_enci_div(p_enc[j].enci_div); + hdmitx_enable_enci_clk(hdev); + } else { + set_encp_div(p_enc[j].encp_div); + hdmitx_enable_encp_clk(hdev); + } } static int likely_frac_rate_mode(char *m) @@ -1136,3 +1173,15 @@ void hdmitx_set_clk(struct hdmitx_dev *hdev) hdmitx_set_clk_(hdev); } +void hdmitx_disable_clk(struct hdmitx_dev *hdev) +{ + /* cts_encp/enci_clk */ + if (hdev->para->hdmitx_vinfo.viu_mux == VIU_MUX_ENCI) + hdmitx_disable_enci_clk(hdev); + else + hdmitx_disable_encp_clk(hdev); + + /* hdmi_tx_pixel_clk */ + hdmitx_disable_tx_pixel_clk(hdev); +} + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h index b45b4e9011ed..90630a69094e 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.h @@ -59,10 +59,7 @@ void hdmitx_set_top_pclk(struct hdmitx_dev *hdev); void hdmitx_set_hdcp_pclk(struct hdmitx_dev *hdev); void hdmitx_set_cts_hdcp22_clk(struct hdmitx_dev *hdev); void hdmitx_set_sys_clk(struct hdmitx_dev *hdev, unsigned char flag); -void hdmitx_set_vclk2_encp(struct hdmitx_dev *hdev); -void hdmitx_disable_vclk2_enci(struct hdmitx_dev *hdev); -void hdmitx_set_vclk2_enci(struct hdmitx_dev *hdev); - +void hdmitx_disable_clk(struct hdmitx_dev *hdev); #endif diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c index e95d231ae7df..e9b2929fb28d 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c @@ -164,12 +164,45 @@ static bool set_hpll_hclk_v3(unsigned int m, unsigned int frac_val) return ret; /* return hpll locked status */ } +#define IS_DONGLE_MODE(hdev) \ + ((hdev->dongle_mode) \ + && (hdev->para->cs == COLORSPACE_YUV422 \ + || hdev->para->cd == COLORDEPTH_24B) \ + && (hdev->cur_VIC == HDMI_1280x720p50_16x9 \ + || hdev->cur_VIC == HDMI_1280x720p60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080i60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080i50_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080p60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080p50_16x9)) + +static void set_hpll_hclk_dongle_5940m(void) +{ + hd_write_reg(P_HHI_HDMI_PLL_CNTL0, 0x0b3a04f7); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0x3, 28, 2); + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x10000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x00100140); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x2a295c00); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x65771290); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x39272000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x50540000); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0x0, 29, 1); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL0); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); +} + void set_g12a_hpll_clk_out(unsigned int frac_rate, unsigned int clk) { + struct hdmitx_dev *hdev = get_hdmitx_device(); unsigned int m, m1, m2; switch (clk) { case 5940000: + if (IS_DONGLE_MODE(hdev)) { + set_hpll_hclk_dongle_5940m(); + break; + } if (set_hpll_hclk_v1(0xf7, frac_rate ? 0x8148 : 0x10000)) break; if (set_hpll_hclk_v2(0x7b, 0x18000)) @@ -401,9 +434,10 @@ int hdmitx_hpd_hw_op_g12a(enum hpd_op cmd) return ret; } - void set_hpll_sspll_g12a(enum hdmi_vic vic) { + struct hdmitx_dev *hdev = get_hdmitx_device(); + switch (vic) { case HDMI_1920x1080p60_16x9: case HDMI_1920x1080p50_16x9: @@ -420,6 +454,8 @@ void set_hpll_sspll_g12a(enum hdmi_vic vic) hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 8, 1); /* 2: 1000ppm 1: 500ppm */ hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 4, 4); + if (hdev->dongle_mode) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 4, 4, 4); /* bit[15] hdmi_dpll_sdmnc_en */ hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL3, 0, 15, 1); hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0, 29, 1); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h index fc673b1a38d0..5d2e6ded6190 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/mach_reg.h @@ -154,6 +154,20 @@ void init_reg_map(unsigned int type); #define PAD_PULL_UP_EN_REG4 0x4c #define P_PAD_PULL_UP_EN_REG4 PERIPHS_REG_ADDR(PAD_PULL_UP_EN_REG4) +#define TM2_HHI_HDMI_PHY_CNTL0 0x05 +#define P_TM2_HHI_HDMI_PHY_CNTL0 HHI_REG_ADDR(TM2_HHI_HDMI_PHY_CNTL0) +#define TM2_HHI_HDMI_PHY_CNTL1 0x06 +#define P_TM2_HHI_HDMI_PHY_CNTL1 HHI_REG_ADDR(TM2_HHI_HDMI_PHY_CNTL1) +#define TM2_HHI_HDMI_PHY_CNTL2 0x07 +#define P_TM2_HHI_HDMI_PHY_CNTL2 HHI_REG_ADDR(TM2_HHI_HDMI_PHY_CNTL2) +#define TM2_HHI_HDMI_PHY_CNTL3 0x08 +#define P_TM2_HHI_HDMI_PHY_CNTL3 HHI_REG_ADDR(TM2_HHI_HDMI_PHY_CNTL3) +#define TM2_HHI_HDMI_PHY_CNTL4 0x09 +#define P_TM2_HHI_HDMI_PHY_CNTL4 HHI_REG_ADDR(TM2_HHI_HDMI_PHY_CNTL4) +#define TM2_HHI_HDMI_PHY_CNTL5 0x0a +#define P_TM2_HHI_HDMI_PHY_CNTL5 HHI_REG_ADDR(TM2_HHI_HDMI_PHY_CNTL5) +#define TM2_HHI_HDMI_PHY_STATUS 0x0d +#define P_TM2_HHI_HDMI_PHY_STATUS HHI_REG_ADDR(TM2_HHI_HDMI_PHY_STATUS) #define HHI_MEM_PD_REG0 0x40 #define P_HHI_MEM_PD_REG0 HHI_REG_ADDR(HHI_MEM_PD_REG0) @@ -210,6 +224,10 @@ void init_reg_map(unsigned int type); #define P_HHI_HDMI_AFC_CNTL HHI_REG_ADDR(HHI_HDMI_AFC_CNTL) #define HHI_VPU_CLKB_CNTL 0x83 #define P_HHI_VPU_CLKB_CNTL HHI_REG_ADDR(HHI_VPU_CLKB_CNTL) +#define HHI_LVDS_TX_PHY_CNTL0 0x9a +#define P_HHI_LVDS_TX_PHY_CNTL0 HHI_REG_ADDR(HHI_LVDS_TX_PHY_CNTL0) +#define HHI_LVDS_TX_PHY_CNTL1 0x9b +#define P_HHI_LVDS_TX_PHY_CNTL1 HHI_REG_ADDR(HHI_LVDS_TX_PHY_CNTL1) #define HHI_VDAC_CNTL0 0xbd #define P_HHI_VDAC_CNTL0 HHI_REG_ADDR(HHI_VDAC_CNTL0) #define HHI_VDAC_CNTL1 0xbe diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c index 7440ed5f1511..02964e07ee17 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c @@ -156,6 +156,46 @@ static struct reg_map reg_maps_g12a[] = { }, }; +/* For TM2 */ +static struct reg_map reg_maps_tm2[] = { + [CBUS_REG_IDX] = { /* CBUS */ + .phy_addr = 0xffd00000, + .size = 0x100000, + }, + [PERIPHS_REG_IDX] = { /* PERIPHS */ + .phy_addr = 0xff634400, + .size = 0x2000, + }, + [VCBUS_REG_IDX] = { /* VPU */ + .phy_addr = 0xff900000, + .size = 0x40000, + }, + [AOBUS_REG_IDX] = { /* RTI */ + .phy_addr = 0xff800000, + .size = 0x100000, + }, + [HHI_REG_IDX] = { /* HIU */ + .phy_addr = 0xff63c000, + .size = 0x2000, + }, + [RESET_CBUS_REG_IDX] = { /* RESET */ + .phy_addr = 0xffd00000, + .size = 0x1100, + }, + [HDMITX_SEC_REG_IDX] = { /* HDMITX DWC LEVEL*/ + .phy_addr = 0xff670000, + .size = 0x8000, + }, + [HDMITX_REG_IDX] = { /* HDMITX TOP LEVEL*/ + .phy_addr = 0xff678000, + .size = 0x4000, + }, + [ELP_ESM_REG_IDX] = { + .phy_addr = 0xffe01000, + .size = 0x100, + }, +}; + static struct reg_map *map; void init_reg_map(unsigned int type) @@ -178,6 +218,19 @@ void init_reg_map(unsigned int type) } } break; + case MESON_CPU_ID_TM2: + map = reg_maps_tm2; + for (i = 0; i < REG_IDX_END; i++) { + map[i].p = ioremap(map[i].phy_addr, map[i].size); + if (!map[i].p) { + pr_info("hdmitx20: failed Mapped PHY: 0x%x\n", + map[i].phy_addr); + } else { + pr_info("hdmitx20: Mapped PHY: 0x%x\n", + map[i].phy_addr); + } + } + break; case MESON_CPU_ID_TXLX: map = reg_maps_txlx; break; @@ -254,6 +307,7 @@ unsigned int hd_read_reg(unsigned int addr) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: default: val = readl(TO_PMAP_ADDR(addr)); break; @@ -304,6 +358,7 @@ void hd_write_reg(unsigned int addr, unsigned int val) case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: case MESON_CPU_ID_SM1: + case MESON_CPU_ID_TM2: default: writel(val, TO_PMAP_ADDR(addr)); break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index 025e0dbcfa04..2bbedbc83b49 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -376,7 +376,13 @@ static void lcd_venc_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - lcd_vcbus_write(ENCL_INBUF_CNTL1, (1 << 14) | (h_active - 1)); + /*[15:14]: 2'b10 or 2'b01*/ + lcd_vcbus_write(ENCL_INBUF_CNTL1, (2 << 14) | (h_active - 1)); + lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); + break; + case LCD_CHIP_TM2: + /*[15:14]: 2'b10 or 2'b01 bit13:1*/ + lcd_vcbus_write(ENCL_INBUF_CNTL1, (5 << 13) | (h_active - 1)); lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); break; default: diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c index 49d701a50533..15996eafe537 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c @@ -472,6 +472,10 @@ static void check_phy_status(void) static void dsi_phy_init(struct dsi_phy_s *dphy, unsigned char lane_num) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct lcd_config_s *pconf; + + pconf = lcd_drv->lcd_config; /* enable phy clock. */ dsi_phy_write(MIPI_DSI_PHY_CTRL, 0x1); /* enable DSI top clock. */ dsi_phy_write(MIPI_DSI_PHY_CTRL, @@ -501,9 +505,18 @@ static void dsi_phy_init(struct dsi_phy_s *dphy, unsigned char lane_num) (dphy->clk_zero << 16) | (dphy->clk_prepare << 24))); dsi_phy_write(MIPI_DSI_CLK_TIM1, dphy->clk_pre); /* ?? */ /* 0x050f090d */ - dsi_phy_write(MIPI_DSI_HS_TIM, - (dphy->hs_exit | (dphy->hs_trail << 8) | - (dphy->hs_zero << 16) | (dphy->hs_prepare << 24))); + if (pconf->lcd_timing.bit_rate > 500000000UL) { /*more than 500M*/ + dsi_phy_write(MIPI_DSI_HS_TIM, + (dphy->hs_exit | (dphy->hs_trail << 8) | + (dphy->hs_zero << 16) | + (dphy->hs_prepare << 24))); + } else { + LCDPR("bit_rata = %d\n", pconf->lcd_timing.bit_rate); + dsi_phy_write(MIPI_DSI_HS_TIM, + (dphy->hs_exit | ((dphy->hs_trail / 2) << 8) | + (dphy->hs_zero << 16) | + (dphy->hs_prepare << 24))); + } /* 0x4a370e0e */ dsi_phy_write(MIPI_DSI_LP_TIM, (dphy->lp_lpx | (dphy->lp_ta_sure << 8) | diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index e2e8f9b13b00..3da722620094 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -330,7 +330,13 @@ static void lcd_venc_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - lcd_vcbus_write(ENCL_INBUF_CNTL1, (1 << 14) | (h_active - 1)); + /*[15:14]: 2'b10 or 2'b01*/ + lcd_vcbus_write(ENCL_INBUF_CNTL1, (2 << 14) | (h_active - 1)); + lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); + break; + case LCD_CHIP_TM2: + /*[15:14]: 2'b10 or 2'b01, bit13:1*/ + lcd_vcbus_write(ENCL_INBUF_CNTL1, (5 << 13) | (h_active - 1)); lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); break; default: diff --git a/drivers/amlogic/media/vout/vout_serve/vout_serve.c b/drivers/amlogic/media/vout/vout_serve/vout_serve.c index 778c9b7d9fe5..ac1a79b34ed1 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_serve.c +++ b/drivers/amlogic/media/vout/vout_serve/vout_serve.c @@ -77,6 +77,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; @@ -896,7 +904,8 @@ static int refresh_tvout_mode(void) { enum vmode_e cur_vmode = VMODE_MAX; char cur_mode_str[VMODE_NAME_LEN_MAX]; - int hpd_state; + int hpd_state = 0; + struct vinfo_s *info = get_current_vinfo(); if (tvout_monitor_flag == 0) return 0; @@ -910,8 +919,25 @@ static int refresh_tvout_mode(void) #endif 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); @@ -1234,6 +1260,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 "); MODULE_DESCRIPTION("VOUT Server Module"); MODULE_LICENSE("GPL");