From df9057779e3076a8fa7a8919475643d8a0466e22 Mon Sep 17 00:00:00 2001 From: Zongdong Jiao Date: Fri, 14 Jun 2019 16:27:19 +0800 Subject: [PATCH] hdmitx: add SCDC/CED function [1/1] PD#SWPL-6361 Problem: Lack SCDC/CED function to check Rx TMDS status Solution: Add SCDC/CED function By default, this function is not open. Enable it in board dts file like below: &amhdmitx { cedst_en = <1>; }; Also, you can manually enable it by 'echo 1 > /sys/class/amhdmitx/amhdmitx0/cedst_policy' Then listen '/sys/class/extcon/hdmi_cedst/uevent' and check 'cat /sys/class/amhdmitx/amhdmitx0/cedst_count' Verify: G12/U212 Change-Id: Ic9c90936bad643ea95d418d7b019eb37210d7123 Signed-off-by: Zongdong Jiao --- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 1 + .../media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c | 152 ++++++++++++++++++++- .../media/vout/hdmitx/hdmi_tx_20/hdmi_tx_scdc.c | 71 ++++++++++ .../media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c | 9 ++ .../linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h | 6 +- .../amlogic/media/vout/hdmi_tx/hdmi_tx_module.h | 28 +++- 6 files changed, 258 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index a42fd8f..8407dab 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -1076,6 +1076,7 @@ */ ic_type = <10>; dongle_mode = <0>; + cedst_en = <0>; vend_data: vend_data{ /* Should modified by Customer */ vendor_name = "Amlogic"; /* Max Chars: 8 */ /* standards.ieee.org/develop/regauth/oui/oui.txt */ 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 8ea929c..3f072ca 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 @@ -111,6 +111,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 inline void hdmitx_notify_hpd(int hpd) { @@ -483,6 +484,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)); @@ -583,6 +586,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; @@ -3031,6 +3038,82 @@ 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; + } 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) { @@ -3593,6 +3676,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); @@ -3679,6 +3764,11 @@ static int hdmitx_module_disable(enum vmode_e cur_vmod) hdmitx_disable_vclk2_enci(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; } @@ -3928,6 +4018,19 @@ 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]; @@ -3951,6 +4054,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 (hdev->RXCap.ieeeoui != HDMI_IEEEOUI) hdev->HWOp.CntlConfig(hdev, @@ -3981,6 +4085,10 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) 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) @@ -4005,6 +4113,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"); @@ -4099,6 +4209,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 */ @@ -4277,6 +4391,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; @@ -4287,13 +4402,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; @@ -4304,13 +4419,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; @@ -4321,30 +4436,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 rxsense*/ + /*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; @@ -4355,17 +4487,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) @@ -4494,6 +4625,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); @@ -4693,6 +4829,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); @@ -4802,6 +4940,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 afb8f5d..54b21c6 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/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index b48e819..171c1db 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 @@ -5001,6 +5001,13 @@ static int hdmitx_tmds_rxsense(void) 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) { @@ -5031,6 +5038,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"); diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h index 45c2d3f..e0be30d 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ddc.h @@ -19,7 +19,7 @@ #define __HDMI_TX_DDC_H__ #include -#include +#include "hdmi_tx_module.h" #define EDID_SLAVE 0x50 #define EDIDSEG_ADR 0x30 @@ -31,6 +31,9 @@ enum scdc_addr { SINK_VER = 0x01, SOURCE_VER, /* RW */ UPDATE_0 = 0x10, /* RW */ +#define STATUS_UPDATE BIT(0) +#define CED_UPDATE BIT(1) +#define RR_TEST BIT(2) UPDATE_1, /* RW */ TMDS_CFG = 0x20, /* RW */ SCRAMBLER_ST, @@ -83,5 +86,6 @@ uint32_t hdcp_rd_hdcp14_ver(void); uint32_t hdcp_rd_hdcp22_ver(void); void scdc_config(struct hdmitx_dev *hdev); void edid_read_head_8bytes(void); +int scdc_status_flags(struct hdmitx_dev *hdev); #endif /* __HDMI_TX_SCDC_H__ */ diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 5b85d43..697407d 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -202,6 +202,23 @@ struct frac_rate_table { u32 sync_den_dec; }; +struct ced_cnt { + bool ch0_valid; + u16 ch0_cnt:15; + bool ch1_valid; + u16 ch1_cnt:15; + bool ch2_valid; + u16 ch2_cnt:15; + u8 chksum; +}; + +struct scdc_locked_st { + u8 clock_detected:1; + u8 ch0_locked:1; + u8 ch1_locked:1; + u8 ch2_locked:1; +}; + enum hdmi_hdr_transfer { T_UNKNOWN = 0, T_BT709, @@ -302,6 +319,7 @@ struct hdmitx_dev { struct notifier_block nb; struct workqueue_struct *hdmi_wq; struct workqueue_struct *rxsense_wq; + struct workqueue_struct *cedst_wq; struct device *hdtx_dev; struct device *pdev; /* for pinctrl*/ struct pinctrl_state *pinctrl_i2c; @@ -310,6 +328,7 @@ struct hdmitx_dev { struct delayed_work work_hpd_plugout; struct delayed_work work_rxsense; struct delayed_work work_internal_intr; + struct delayed_work work_cedst; struct work_struct work_hdr; struct delayed_work work_do_hdcp; #ifdef CONFIG_AML_HDMI_TX_14 @@ -422,6 +441,9 @@ struct hdmitx_dev { /* 0.1% clock shift, 1080p60hz->59.94hz */ unsigned int frac_rate_policy; unsigned int rxsense_policy; + unsigned int cedst_policy; + struct ced_cnt ced_cnt; + struct scdc_locked_st chlocked_st; /* allm_mode: 1/game, 2/graphcis, 3/photo, 4/cinema */ unsigned int allm_mode; unsigned int sspll; @@ -449,6 +471,7 @@ struct hdmitx_dev { unsigned int flag_3dtb:1; unsigned int flag_3dss:1; unsigned int dongle_mode:1; + unsigned int cedst_en:1; /* configure in DTS */ unsigned int drm_feature;/*Direct Rander Management*/ }; @@ -564,9 +587,10 @@ struct hdmitx_dev { #define MISC_ESM_RESET (CMD_MISC_OFFSET + 0x0d) #define MISC_HDCP_CLKDIS (CMD_MISC_OFFSET + 0x0e) #define MISC_TMDS_RXSENSE (CMD_MISC_OFFSET + 0x0f) -#define MISC_I2C_REACTIVE (CMD_MISC_OFFSET + 0x10) -#define MISC_I2C_RESET (CMD_MISC_OFFSET + 0x11) +#define MISC_I2C_REACTIVE (CMD_MISC_OFFSET + 0x10) /* For gxl */ +#define MISC_I2C_RESET (CMD_MISC_OFFSET + 0x11) /* For g12 */ #define MISC_READ_AVMUTE_OP (CMD_MISC_OFFSET + 0x12) +#define MISC_TMDS_CEDST (CMD_MISC_OFFSET + 0x13) /*********************************************************************** * Get State //GetState -- 2.7.4