hdmirx: add hdmirx repeater function [1/6]
authorhongmin hua <hongmin.hua@amlogic.com>
Sun, 30 Sep 2018 03:06:17 +0000 (11:06 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Tue, 30 Oct 2018 11:37:06 +0000 (04:37 -0700)
PD#SWPL-323:

Problem:
add hdmi repeater function

Solution:
1.add the edid receive and mix.
2.add the flow of repeater.

Verify:
R321

Change-Id: I9942c5f345e2fdfff110f01d4d0c2b4b23120c07
Signed-off-by: hongmin hua <hongmin.hua@amlogic.com>
12 files changed:
drivers/amlogic/esm/hdcp_main.c
drivers/amlogic/media/vin/tvin/hdmirx/hdcp_rx_main.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_edid.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_eq.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_repeater.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_repeater.h
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c

index cbddd87..f7d8ecb 100644 (file)
@@ -63,6 +63,8 @@ struct esm_device {
        dma_addr_t data_base;
        uint32_t data_size;
        uint8_t *data;
+
+       struct dentry *esm_blob;
        struct debugfs_blob_wrapper blob;
        struct resource *hpi_resource;
        uint8_t __iomem *hpi;
@@ -106,7 +108,7 @@ static long load_code(struct esm_device *esm, struct esm_ioc_code __user *arg)
        if (copy_from_user(esm->code, &arg->data, head.len) != 0)
                return -EFAULT;
 
-       esm->code_loaded = 1;
+       /* esm->code_loaded = 1; */
                return 0;
 }
 
@@ -233,7 +235,7 @@ static struct esm_device *alloc_esm_slot(const struct esm_ioc_meminfo *info)
 }
 
 static struct dentry *esm_debugfs;
-static struct dentry *esm_blob;
+/*static struct dentry *esm_blob;*/
 
 static void free_dma_areas(struct esm_device *esm)
 {
@@ -255,6 +257,8 @@ static void free_dma_areas(struct esm_device *esm)
 static int alloc_dma_areas(struct esm_device *esm,
        const struct esm_ioc_meminfo *info)
 {
+       char blobname[32];
+
        esm->code_size = info->code_size;
        esm->code_is_phys_mem = (info->code_base != 0);
 
@@ -289,20 +293,24 @@ static int alloc_dma_areas(struct esm_device *esm,
                        return -ENOMEM;
                }
        }
-       /* add blob note to show esm feature and debug*/
-       esm_debugfs = debugfs_create_dir("esm", NULL);
-       if (!esm_debugfs)
-               return -ENOENT;
-
-       esm->blob.data = (void *)esm->code;
-       esm->blob.size = esm->code_size;
-       esm_blob = debugfs_create_blob("blob", 0644, esm_debugfs, &esm->blob);
 
        if (randomize_mem) {
                prandom_bytes(esm->code, esm->code_size);
                prandom_bytes(esm->data, esm->data_size);
        }
 
+       if (!esm_debugfs) {
+               esm_debugfs = debugfs_create_dir("esm", NULL);
+               if (!esm_debugfs)
+                       return -ENOENT;
+       }
+       memset(blobname, 0, sizeof(blobname));
+       sprintf(blobname, "blob.%x", info->hpi_base);
+       esm->blob.data = (void *)esm->data;
+       esm->blob.size = esm->data_size;
+       esm->esm_blob = debugfs_create_blob(blobname, 0644, esm_debugfs,
+               &esm->blob);
+
        return 0;
 }
 
@@ -312,6 +320,7 @@ static long init(struct file *f, void __user *arg)
        struct resource *hpi_mem;
        struct esm_ioc_meminfo info;
        struct esm_device *esm;
+       char region_name[20];
        int rc;
 
        if (copy_from_user(&info, arg, sizeof(info)) != 0)
@@ -325,8 +334,15 @@ static long init(struct file *f, void __user *arg)
                rc = alloc_dma_areas(esm, &info);
                if (rc < 0)
                        goto err_free;
-               pr_info("info.hpi_base = 0x%x\n", info.hpi_base);
-               hpi_mem = request_mem_region(info.hpi_base, 128, "esm-hpi");
+               /* pr_info("info.hpi_base = 0x%x\n", info.hpi_base); */
+               /* hpi_mem =
+                *      request_mem_region(info.hpi_base, 128, "esm-hpi");
+                */
+               sprintf(region_name, "ESM-%X", info.hpi_base);
+               pr_info("info.hpi_base = 0x%x region_name:%s\n",
+                       info.hpi_base, region_name);
+               hpi_mem = request_mem_region(info.hpi_base, 0x100, region_name);
+
                if (!hpi_mem) {
                        rc = -EADDRNOTAVAIL;
                        goto err_free;
@@ -342,6 +358,12 @@ static long init(struct file *f, void __user *arg)
                esm->initialized = 1;
        }
 
+       /*every time clear the data buff*/
+       if (esm->data)
+               memset(esm->data, 0, esm->data_size);
+       pr_info("esm data = %p size:%d\n",
+                       esm->data, esm->data_size);
+
        f->private_data = esm;
                return 0;
 
index d52b9f6..dbd19a6 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/debugfs.h>
 #include <linux/version.h>
 #include "hdcp_rx_main.h"
+#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_drv.h"
 #include "hdmi_rx_hw.h"
 
index 4ddf66b..b86c6d9 100644 (file)
@@ -53,6 +53,7 @@
 #endif
 
 /* Local include */
+#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_drv.h"
 #include "hdmi_rx_wrapper.h"
 #include "hdmi_rx_hw.h"
@@ -60,7 +61,6 @@
 #include "hdmi_rx_edid.h"
 #include "hdmi_rx_eq.h"
 #include "hdmi_rx_repeater.h"
-
 /*------------------------extern function------------------------------*/
 static int aml_hdcp22_pm_notify(struct notifier_block *nb,
        unsigned long event, void *dummy);
@@ -113,6 +113,10 @@ int hdmi_yuv444_enable;
 module_param(hdmi_yuv444_enable, int, 0664);
 MODULE_PARM_DESC(hdmi_yuv444_enable, "hdmi_yuv444_enable");
 
+bool downstream_repeat_support;
+MODULE_PARM_DESC(downstream_repeat_support, "\n downstream_repeat_support\n");
+module_param(downstream_repeat_support, bool, 0664);
+
 int pc_mode_en;
 MODULE_PARM_DESC(pc_mode_en, "\n pc_mode_en\n");
 module_param(pc_mode_en, int, 0664);
@@ -259,6 +263,11 @@ unsigned int rx_set_bits(unsigned int data,
        return ((value << first_bit_set(mask)) & mask) | (data & ~mask);
 }
 
+bool hdmirx_repeat_support(void)
+{
+       return downstream_repeat_support;
+}
+
 /*
  * hdmirx_dec_support - check if given port is supported
  * @fe: frontend device of tvin interface
@@ -940,14 +949,13 @@ static long hdmirx_ioctl(struct file *file, unsigned int cmd,
        case HDMI_IOC_HDCP_ON:
                hdcp_enable = 1;
                rx_set_cur_hpd(0);
-               fsm_restart();
+               /*fsm_restart();*/
                break;
        case HDMI_IOC_HDCP_OFF:
                hdcp_enable = 0;
                rx_set_cur_hpd(0);
                hdmirx_hw_config();
-               hdmi_rx_top_edid_update();
-               fsm_restart();
+               /*fsm_restart();*/
                break;
        case HDMI_IOC_EDID_UPDATE:
                if (rx.open_fg) {
@@ -1356,11 +1364,100 @@ static ssize_t cec_get_state(struct device *dev,
        return 0;
 }
 
-/*
+static ssize_t hdcp_version_show(struct device *dev,
+       struct device_attribute *attr,
+       char *buf)
+{
+       return sprintf(buf, "%x\n", rx.hdcp.hdcp_version);
+}
+
+static ssize_t hdcp_version_store(struct device *dev,
+       struct device_attribute *attr,
+       const char *buf,
+       size_t count)
+{
+       return count;
+}
+
+static ssize_t hw_info_show(struct device *dev,
+       struct device_attribute *attr,
+       char *buf)
+{
+       struct hdcp_hw_info_s info;
+
+       memset(&info, 0, sizeof(info));
+       info.cur_5v = rx.cur_5v_sts;
+       info.open = rx.open_fg;
+       info.frame_rate = rx.pre.frame_rate/100;
+       info.signal_stable = ((rx.state == FSM_SIG_READY)?1:0);
+       return sprintf(buf, "%x\n", *((unsigned int *)&info));
+}
+
+static ssize_t hw_info_store(struct device *dev,
+       struct device_attribute *attr,
+       const char *buf,
+       size_t count)
+{
+       return count;
+}
+
+static ssize_t edid_dw_show(struct device *dev,
+       struct device_attribute *attr,
+       char *buf)
+{
+       return 0;
+}
+
+static ssize_t edid_dw_store(struct device *dev,
+       struct device_attribute *attr,
+       const char *buf,
+       size_t count)
+{
+       int cnt = count;
+
+       rx_pr("edid store len: %d\n", cnt);
+       rx_set_receiver_edid(buf, cnt);
+
+       return count;
+}
+
+static ssize_t ksvlist_show(struct device *dev,
+       struct device_attribute *attr,
+       char *buf)
+{
+       return 0;
+}
+
+static ssize_t ksvlist_store(struct device *dev,
+       struct device_attribute *attr,
+       const char *buf,
+       size_t count)
+{
+       int cnt;
+       /* unsigned long tmp; */
+       unsigned char *hdcp = rx_get_dw_hdcp_addr();
+       /* unsigned char t_tmp[3]; */
+       cnt = count;
+       /* t_tmp[2] = '\0'; */
+       rx_pr("dw hdcp %d,%d\n", cnt, sizeof(struct hdcp14_topo_s));
+       /*for(i = 0;i < count/2;i++) {
+        *      memcpy(t_tmp, buf + i*2, 2);
+        *      if (kstrtoul(t_tmp, 16, &tmp))
+        *      rx_pr("ksvlist %s:\n", t_tmp);
+        *      *(hdcp + i) = (unsigned char)tmp;
+        *      rx_pr("%#x ", *(hdcp + i));
+        *}
+        */
+       memcpy(hdcp, buf, cnt);
+       rx_pr("\n");
+       return count;
+}
+
+/*************************************
  *  val == 0 : cec disable
  *  val == 1 : cec on
  *  val == 2 : cec on && system startup
- */
+ **************************************/
 static ssize_t cec_set_state(struct device *dev,
        struct device_attribute *attr,
        const char *buf,
@@ -1460,6 +1557,25 @@ static ssize_t get_arc_aud_type(struct device *dev,
        return 0;
 }
 
+static ssize_t set_reset_hdcp22(struct device *dev,
+       struct device_attribute *attr,
+       const char *buf,
+       size_t count)
+{
+       int reset;
+
+       memcpy(&reset, buf, sizeof(reset));
+       rx_pr("%s:%d\n", __func__, reset);
+       rx_reload_firm_reset(reset);
+       return count;
+}
+
+static ssize_t get_reset_hdcp22(struct device *dev,
+       struct device_attribute *attr,
+       char *buf)
+{
+       return 0;
+}
 static DEVICE_ATTR(debug, 0644, hdmirx_debug_show, hdmirx_debug_store);
 static DEVICE_ATTR(edid, 0644, hdmirx_edid_show, hdmirx_edid_store);
 static DEVICE_ATTR(key, 0644, hdmirx_key_show, hdmirx_key_store);
@@ -1470,7 +1586,11 @@ static DEVICE_ATTR(param, 0644, param_get_value, param_set_value);
 static DEVICE_ATTR(esm_base, 0644, esm_get_base, esm_set_base);
 static DEVICE_ATTR(info, 0644, show_info, store_info);
 static DEVICE_ATTR(arc_aud_type, 0644, get_arc_aud_type, set_arc_aud_type);
-
+static DEVICE_ATTR(reset22, 0644, get_reset_hdcp22, set_reset_hdcp22);
+static DEVICE_ATTR(hdcp_version, 0644, hdcp_version_show, hdcp_version_store);
+static DEVICE_ATTR(hw_info, 0644, hw_info_show, hw_info_store);
+static DEVICE_ATTR(edid_dw, 0644, edid_dw_show, edid_dw_store);
+static DEVICE_ATTR(ksvlist, 0644, ksvlist_show, ksvlist_store);
 
 static int hdmirx_add_cdev(struct cdev *cdevp,
                const struct file_operations *fops,
@@ -1808,6 +1928,32 @@ static int hdmirx_probe(struct platform_device *pdev)
                        rx_pr("hdmirx: fail to create arc_aud_type file\n");
                        goto fail_create_arc_aud_type_file;
                }
+       ret = device_create_file(hdevp->dev, &dev_attr_reset22);
+       if (ret < 0) {
+               rx_pr("hdmirx: fail to create reset22 file\n");
+               goto fail_create_reset22;
+       }
+       ret = device_create_file(hdevp->dev, &dev_attr_hdcp_version);
+       if (ret < 0) {
+               rx_pr("hdmirx: fail to create hdcp version file\n");
+               goto fail_create_hdcp_version;
+       }
+       ret = device_create_file(hdevp->dev, &dev_attr_hw_info);
+       if (ret < 0) {
+               rx_pr("hdmirx: fail to create cur 5v file\n");
+               goto fail_create_hw_info;
+       }
+       ret = device_create_file(hdevp->dev, &dev_attr_edid_dw);
+       if (ret < 0) {
+               rx_pr("hdmirx: fail to create edid_dw file\n");
+               goto fail_create_edid_dw;
+       }
+       ret = device_create_file(hdevp->dev, &dev_attr_ksvlist);
+       if (ret < 0) {
+               rx_pr("hdmirx: fail to create ksvlist file\n");
+               goto fail_create_ksvlist;
+       }
+
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res) {
                rx_pr("%s: can't get irq resource\n", __func__);
@@ -1946,8 +2092,8 @@ static int hdmirx_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&esm_dwork, rx_hpd_to_esm_handle);
        /* queue_delayed_work(eq_wq, &eq_dwork, msecs_to_jiffies(5)); */
 
-       repeater_wq = create_singlethread_workqueue(hdevp->frontend.name);
-       INIT_DELAYED_WORK(&repeater_dwork, repeater_dwork_handle);
+       /*repeater_wq = create_singlethread_workqueue(hdevp->frontend.name);*/
+       /*INIT_DELAYED_WORK(&repeater_dwork, repeater_dwork_handle);*/
 
        ret = of_property_read_u32(pdev->dev.of_node,
                                "en_4k_2_2k", &en_4k_2_2k);
@@ -1998,6 +2144,16 @@ fail_kmalloc_pd_fifo:
        return ret;
 fail_get_resource_irq:
        return ret;
+fail_create_ksvlist:
+       device_remove_file(hdevp->dev, &dev_attr_ksvlist);
+fail_create_edid_dw:
+       device_remove_file(hdevp->dev, &dev_attr_edid_dw);
+fail_create_hw_info:
+       device_remove_file(hdevp->dev, &dev_attr_hw_info);
+fail_create_hdcp_version:
+       device_remove_file(hdevp->dev, &dev_attr_hdcp_version);
+fail_create_reset22:
+       device_remove_file(hdevp->dev, &dev_attr_reset22);
 fail_create_arc_aud_type_file:
        device_remove_file(hdevp->dev, &dev_attr_arc_aud_type);
 fail_create_cec_file:
@@ -2055,6 +2211,11 @@ static int hdmirx_remove(struct platform_device *pdev)
        device_remove_file(hdevp->dev, &dev_attr_esm_base);
        device_remove_file(hdevp->dev, &dev_attr_info);
        device_remove_file(hdevp->dev, &dev_attr_arc_aud_type);
+       device_remove_file(hdevp->dev, &dev_attr_ksvlist);
+       device_remove_file(hdevp->dev, &dev_attr_edid_dw);
+       device_remove_file(hdevp->dev, &dev_attr_hw_info);
+       device_remove_file(hdevp->dev, &dev_attr_hdcp_version);
+       device_remove_file(hdevp->dev, &dev_attr_reset22);
        tvin_unreg_frontend(&hdevp->frontend);
        hdmirx_delete_device(hdevp->index);
        tasklet_kill(&rx_tasklet);
@@ -2071,7 +2232,8 @@ static int aml_hdcp22_pm_notify(struct notifier_block *nb,
 {
        int delay = 0;
 
-       if (event == PM_SUSPEND_PREPARE && hdcp22_on) {
+       if ((event == PM_SUSPEND_PREPARE) && hdcp22_on) {
+               rx_pr("PM_SUSPEND_PREPARE\n");
                hdcp22_kill_esm = 1;
                /*wait time out ESM_KILL_WAIT_TIMES*20 ms*/
                while (delay++ < ESM_KILL_WAIT_TIMES) {
@@ -2079,10 +2241,15 @@ static int aml_hdcp22_pm_notify(struct notifier_block *nb,
                                break;
                        msleep(20);
                }
-               if (delay < ESM_KILL_WAIT_TIMES)
+               if (!hdcp22_kill_esm)
                        rx_pr("hdcp22 kill ok!\n");
                else
                        rx_pr("hdcp22 kill timeout!\n");
+               hdcp22_kill_esm = 0;
+               hdcp22_suspend();
+       } else if ((event == PM_POST_SUSPEND) && hdcp22_on) {
+               rx_pr("PM_POST_SUSPEND\n");
+               hdcp22_resume();
        }
        return NOTIFY_OK;
 }
@@ -2099,8 +2266,6 @@ static int hdmirx_suspend(struct platform_device *pdev, pm_message_t state)
        if (!early_suspend_flag)
 #endif
                rx_phy_suspend();
-       if (hdcp22_on)
-               hdcp22_suspend();
        rx_pr("hdmirx: suspend success\n");
        return 0;
 }
@@ -2116,8 +2281,7 @@ static int hdmirx_resume(struct platform_device *pdev)
        if (!early_suspend_flag)
 #endif
                rx_phy_resume();
-       if (hdcp22_on)
-               hdcp22_resume();
+
        rx_pr("hdmirx: resume\n");
        return 0;
 }
index ee05f9e..0e6fb09 100644 (file)
@@ -46,7 +46,7 @@
  *
  *
  */
-#define RX_VER2 "ver.2018/09/06"
+#define RX_VER2 "ver.2018/10/30"
 
 /*print type*/
 #define        LOG_EN          0x01
@@ -271,6 +271,8 @@ struct rx_video_info {
  * @short HDMI RX controller HDCP configuration
  */
 struct hdmi_rx_hdcp {
+       /*hdcp auth state*/
+       enum repeater_state_e state;
        /** Repeater mode else receiver only */
        bool repeat;
        bool cascade_exceed;
@@ -394,6 +396,7 @@ struct rx_s {
        bool boot_flag;
        bool open_fg;
        uint8_t irq_flag;
+       bool firm_change;/*hdcp2.2 rp/rx switch time*/
        /** HDMI RX controller HDCP configuration */
        struct hdmi_rx_hdcp hdcp;
        /*report hpd status to app*/
@@ -452,6 +455,7 @@ extern struct tasklet_struct rx_tasklet;
 extern struct device *hdmirx_dev;
 extern struct rx_s rx;
 extern struct reg_map reg_maps[MAP_ADDR_MODULE_NUM];
+extern bool downstream_repeat_support;
 extern void rx_tasklet_handler(unsigned long arg);
 extern void skip_frame(unsigned int cnt);
 
@@ -509,6 +513,7 @@ bool hdmirx_repeat_support(void);
 
 /* edid-hdcp14 */
 extern unsigned int edid_update_flag;
+extern unsigned int downstream_hpd_flag;
 
 extern void hdmirx_fill_edid_buf(const char *buf, int size);
 extern unsigned int hdmirx_read_edid_buf(char *buf, int max_size);
index 7a81a4d..c94ee5b 100644 (file)
@@ -30,9 +30,9 @@
 #include <linux/cdev.h>
 
 /* Local include */
+#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_drv.h"
 #include "hdmi_rx_edid.h"
-#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_hw.h"
 
 static unsigned char edid_temp[EDID_SIZE];
@@ -810,7 +810,7 @@ void rx_edid_update_audio_info(unsigned char *p_edid,
 {
        if (p_edid == NULL)
                return;
-       rx_modify_edid(p_edid, len, rx_get_receiver_edid());
+       rx_modify_edid(p_edid, len, rx_get_dw_edid_addr());
 }
 
 unsigned int rx_edid_cal_phy_addr(
index a5c5d7a..31bbcd3 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/amlogic/media/frame_provider/tvin/tvin.h>
 /* Local include */
+#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_eq.h"
 #include "hdmi_rx_drv.h"
 #include "hdmi_rx_hw.h"
index 526ed63..7ac74de 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/arm-smccc.h>
 
 /* Local include */
+#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_drv.h"
 #include "hdmi_rx_hw.h"
 #include "hdmi_rx_edid.h"
@@ -628,11 +629,14 @@ unsigned int rx_sec_reg_read(unsigned int *addr)
 /*
  * rx_sec_set_duk
  */
-unsigned int rx_sec_set_duk(void)
+unsigned int rx_sec_set_duk(bool repeater)
 {
        struct arm_smccc_res res;
 
-       arm_smccc_smc(HDCP22_RX_SET_DUK_KEY, 0, 0, 0, 0, 0, 0, 0, &res);
+       if (repeater)
+               arm_smccc_smc(HDCP22_RP_SET_DUK_KEY, 0, 0, 0, 0, 0, 0, 0, &res);
+       else
+               arm_smccc_smc(HDCP22_RX_SET_DUK_KEY, 0, 0, 0, 0, 0, 0, 0, &res);
 
        return (unsigned int)((res.a0)&0xffffffff);
 }
@@ -1561,7 +1565,7 @@ int rx_is_hdcp22_support(void)
 {
        int ret = 0;
 
-       if (rx_sec_set_duk() == 1) {
+       if (rx_sec_set_duk(hdmirx_repeat_support()) == 1) {
                rx_hdcp22_wr_top(TOP_SKP_CNTL_STAT, 7);
                ret = 1;
        } else
@@ -2080,6 +2084,47 @@ void rx_hdcp_init(void)
                hdmirx_wr_bits_dwc(DWC_HDCP_CTRL, ENCRIPTION_ENABLE, 0);
 }
 
+/*type 1 pull down hpd,reset hdcp2.2
+ *type 2 only pull down hpd
+ */
+void hdmirx_load_firm_reset(int type)
+{
+       int ret = 0;
+
+       rx_pr("%s\n", __func__);
+       rx_pr("3firm_change:%d,repeat_plug:%d,repeat:%d\n",
+                               rx.firm_change, repeat_plug, rx.hdcp.repeat);
+       /*wait the fsm end*/
+       rx.firm_change = 1;
+       msleep(20);
+       /*External_Mute(1);rx_aud_pll_ctl(0);*/
+       rx_set_cur_hpd(0);
+       /*type 2 only pull down hpd*/
+       if (type == 2) {
+               downstream_hpd_flag = 0;
+               fsm_restart();
+               return;
+       }
+       if (!repeat_plug)
+               downstream_hpd_flag = 1;
+       else
+               downstream_hpd_flag = 0;
+       ret = rx_sec_set_duk(hdmirx_repeat_support());
+       rx_pr("ret = %d\n", ret);
+       if (ret == 1) {
+               hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0x0);
+               hdmirx_hdcp22_esm_rst();
+               mdelay(100);
+               hdmirx_wr_dwc(DWC_HDCP22_CONTROL,
+                                       0x1000);
+               rx_hdcp22_wr_top(TOP_SKP_CNTL_STAT, 0x1);
+               fsm_restart();
+               rx_is_hdcp22_support();
+       }
+       rx_pr("4firm_change:%d,repeat_plug:%d,repeat:%d\n",
+                       rx.firm_change, repeat_plug, rx.hdcp.repeat);
+}
+
 /* need reset bandgap when
  * aud_clk=0 & req_clk!=0
  * according to analog team's request
@@ -2670,7 +2715,7 @@ void rx_debug_load22key(void)
        int ret = 0;
        int wait_kill_done_cnt = 0;
 
-       ret = rx_sec_set_duk();
+       ret = rx_sec_set_duk(hdmirx_repeat_support());
        rx_pr("22 = %d\n", ret);
        if (ret == 1) {
                rx_pr("load 2.2 key\n");
index c56d304..6d982f8 100644 (file)
 #define HDCP22_RX_ESM_READ     0x8200001f
 #define HDCP22_RX_ESM_WRITE    0x8200002f
 #define HDCP22_RX_SET_DUK_KEY  0x8200002e
+#define HDCP22_RP_SET_DUK_KEY  0x8200002c
 #define HDCP14_RX_SETKEY       0x8200002d
 
 enum hdcp14_key_mode_e {
@@ -1154,11 +1155,12 @@ extern unsigned int sec_top_read(unsigned int *addr);
 extern void sec_top_write(unsigned int *addr, unsigned int value);
 extern void rx_esm_tmdsclk_en(bool en);
 extern int hdcp22_on;
+extern int hdcp14_on;
 extern bool hdcp22_kill_esm;
 extern bool hpd_to_esm;
 extern void hdcp22_clk_en(bool en);
 extern void hdmirx_hdcp22_esm_rst(void);
-extern unsigned int rx_sec_set_duk(void);
+extern unsigned int rx_sec_set_duk(bool repeater);
 extern void hdmirx_hdcp22_init(void);
 extern void hdcp22_suspend(void);
 extern void hdcp22_resume(void);
@@ -1166,8 +1168,8 @@ extern void hdmirx_hdcp22_hpd(bool value);
 extern void esm_set_reset(bool reset);
 extern void esm_set_stable(bool stable);
 extern void rx_hpd_to_esm_handle(struct work_struct *work);
-
-
+extern void rx_hdcp14_resume(void);
+extern void hdmirx_load_firm_reset(int type);
 extern unsigned int hdmirx_packet_fifo_rst(void);
 extern unsigned int hdmirx_audio_fifo_rst(void);
 extern void hdmirx_phy_init(void);
index dcaafe1..d0ba34c 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/cdev.h>
 
 /* Local include */
+#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_pktinfo.h"
 #include "hdmi_rx_drv.h"
 #include "hdmi_rx_hw.h"
index 47bff53..e3a1e3d 100644 (file)
@@ -37,9 +37,9 @@
 #include <linux/amlogic/media/frame_provider/tvin/tvin.h>
 
 /* Local include */
+#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_drv.h"
 #include "hdmi_rx_hw.h"
-#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_wrapper.h"
 #include "hdmi_rx_edid.h"
 /*edid original data from device*/
@@ -47,6 +47,9 @@ static unsigned char receive_edid[MAX_RECEIVE_EDID];
 int receive_edid_len = MAX_RECEIVE_EDID;
 MODULE_PARM_DESC(receive_edid, "\n receive_edid\n");
 module_param_array(receive_edid, byte, &receive_edid_len, 0664);
+int edid_len;
+MODULE_PARM_DESC(edid_len, "\n edid_len\n");
+module_param(edid_len, int, 0664);
 bool new_edid;
 /*original bksv from device*/
 static unsigned char receive_hdcp[MAX_KSV_LIST_SIZE];
@@ -56,77 +59,79 @@ module_param_array(receive_hdcp, byte, &hdcp_array_len, 0664);
 int hdcp_len;
 int hdcp_repeat_depth;
 bool new_hdcp;
-bool repeat_plug;
-int up_phy_addr;/*d c b a 4bit*/
+bool start_auth_14;
+MODULE_PARM_DESC(start_auth_14, "\n start_auth_14\n");
+module_param(start_auth_14, bool, 0664);
 
-bool downstream_rp_en;
+bool repeat_plug;
+MODULE_PARM_DESC(repeat_plug, "\n repeat_plug\n");
+module_param(repeat_plug, bool, 0664);
 
-enum repeater_state_e rpt_state;
+int up_phy_addr;/*d c b a 4bit*/
+MODULE_PARM_DESC(up_phy_addr, "\n up_phy_addr\n");
+module_param(up_phy_addr, int, 0664);
+int hdcp22_firm_switch_timeout;
 
-bool hdmirx_repeat_support(void)
+unsigned char *rx_get_dw_hdcp_addr(void)
 {
-       return downstream_rp_en;
+       return receive_hdcp;
 }
 
 void rx_start_repeater_auth(void)
 {
-       rpt_state = REPEATER_STATE_START;
+       rx.hdcp.state = REPEATER_STATE_START;
+       start_auth_14 = 1;
        rx.hdcp.delay = 0;
        hdcp_len = 0;
        hdcp_repeat_depth = 0;
        rx.hdcp.dev_exceed = 0;
        rx.hdcp.cascade_exceed = 0;
+       rx.hdcp.depth = 0;
+       rx.hdcp.count = 0;
        memset(&receive_hdcp, 0, sizeof(receive_hdcp));
 }
 
-void repeater_dwork_handle(struct work_struct *work)
-{
-       if (hdmirx_repeat_support()) {
-               if (rx.hdcp.hdcp_version && hdmirx_is_key_write()
-                       && rx.open_fg) {
-                       extcon_set_state_sync(rx.hdcp.rx_excton_auth,
-                               EXTCON_DISP_HDMI, 0);
-                       extcon_set_state_sync(rx.hdcp.rx_excton_auth,
-                               EXTCON_DISP_HDMI, rx.hdcp.hdcp_version);
-               }
-       }
-}
-
-bool hdmirx_is_key_write(void)
-{
-       if (hdmirx_rd_dwc(DWC_HDCP_BKSV0) != 0)
-               return 1;
-       else
-               return 0;
-}
-
 void rx_check_repeat(void)
 {
+       struct hdcp14_topo_s *topo_data = (struct hdcp14_topo_s *)receive_hdcp;
+
        if (!hdmirx_repeat_support())
                return;
 
        if (rx.hdcp.repeat != repeat_plug) {
+               /*pull down hpd if downstream plug low*/
+               rx_set_cur_hpd(0);
+               rx_pr("firm_change:%d,repeat_plug:%d,repeat:%d\n",
+                       rx.firm_change, repeat_plug, rx.hdcp.repeat);
                rx_set_repeat_signal(repeat_plug);
                if (!repeat_plug) {
-                       hdcp_len = 0;
-                       hdcp_repeat_depth = 0;
+                       edid_len = 0;
                        rx.hdcp.dev_exceed = 0;
                        rx.hdcp.cascade_exceed = 0;
                        memset(&receive_hdcp, 0, sizeof(receive_hdcp));
-                       new_edid = true;
                        memset(&receive_edid, 0, sizeof(receive_edid));
-                       rx_send_hpd_pulse();
+                       up_phy_addr = 0;
+                       /*new_edid = true;*/
+                       /* rx_set_cur_hpd(1); */
+                       /*rx.firm_change = 0;*/
+                       rx_pr("1firm_change:%d,repeat_plug:%d,repeat:%d\n",
+                               rx.firm_change, repeat_plug, rx.hdcp.repeat);
                }
        }
-       if (new_edid) {
+
+       /*this is addition for the downstream edid too late*/
+       if (new_edid && rx.hdcp.repeat && (!rx.firm_change)) {
                /*check downstream plug when new plug occur*/
                /*check receive change*/
+               /*it's contained in hwconfig*/
                hdmi_rx_top_edid_update();
+               hdcp22_firm_switch_timeout = 0;
                new_edid = false;
                rx_send_hpd_pulse();
        }
+
        if (repeat_plug) {
-               switch (rpt_state) {
+               switch (rx.hdcp.state) {
                case REPEATER_STATE_START:
                        rx_pr("[RX] receive aksv\n");
                        hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL,
@@ -135,12 +140,16 @@ void rx_check_repeat(void)
                                                KSVLIST_LOSTAUTH, 0);
                        hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL,
                                                KSVLIST_READY, 0);
-                       rpt_state = REPEATER_STATE_WAIT_KSV;
+                       hdmirx_wr_bits_dwc(DWC_HDCP_RPT_BSTATUS,
+                               MAX_CASCADE_EXCEEDED, 0);
+                       hdmirx_wr_bits_dwc(DWC_HDCP_RPT_BSTATUS,
+                               MAX_DEVS_EXCEEDED, 0);
+                       rx.hdcp.state = REPEATER_STATE_WAIT_KSV;
                break;
 
                case REPEATER_STATE_WAIT_KSV:
                if (!rx.cur_5v_sts) {
-                       rpt_state = REPEATER_STATE_IDLE;
+                       rx.hdcp.state = REPEATER_STATE_IDLE;
                        break;
                }
                if (hdmirx_rd_bits_dwc(DWC_HDCP_RPT_CTRL, WAITING_KSV)) {
@@ -152,13 +161,14 @@ void rx_check_repeat(void)
                        } else if (rx.hdcp.delay >= KSV_LIST_WAIT_DELAY) {
                                hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL,
                                                KSVLIST_TIMEOUT, 1);
-                               rpt_state = REPEATER_STATE_IDLE;
+                               rx.hdcp.state = REPEATER_STATE_IDLE;
                                rx_pr("[RX] receive ksv wait timeout\n");
                        }
-                       if (rx_set_repeat_aksv(receive_hdcp, hdcp_len,
-                               hdcp_repeat_depth, rx.hdcp.dev_exceed,
-                               rx.hdcp.cascade_exceed)) {
-                               rpt_state = REPEATER_STATE_IDLE;
+                       if (rx_set_repeat_aksv(topo_data->ksv_list,
+                               topo_data->device_count,
+                               topo_data->depth, topo_data->max_devs_exceeded,
+                               topo_data->max_cascade_exceeded)) {
+                               rx.hdcp.state = REPEATER_STATE_IDLE;
                        }
                }
                /*if support hdcp2.2 jump to wait_ack else to idle*/
@@ -184,27 +194,58 @@ void rx_check_repeat(void)
        /*}*/
 }
 
-unsigned char *rx_get_receiver_edid(void)
+void rx_reload_firm_reset(int reset)
+{
+       if (reset)
+               hdmirx_load_firm_reset(reset);
+       else
+               rx_firm_reset_end();
+}
+
+void rx_firm_reset_end(void)
+{
+       rx_pr("%s new_edid:%d\n", __func__, new_edid);
+       if (new_edid) {
+               new_edid = 0;
+               hdmi_rx_top_edid_update();
+       }
+       rx.firm_change = 0;
+}
+unsigned char *rx_get_dw_edid_addr(void)
 {
        return receive_edid;
 }
 
-int rx_set_receiver_edid(unsigned char *data, int len)
+int rx_set_receiver_edid(const char *data, int len)
 {
-       if ((data == NULL) || (len == 0) || (len > MAX_RECEIVE_EDID))
+       if ((data == NULL) || (len == 0))
                return false;
 
-       memset(receive_edid, 0, sizeof(receive_edid));
-       if ((len > 0) && (*data != 0))
+       if ((len > MAX_RECEIVE_EDID) || (len < 3)) {
+               memset(receive_edid, 0, sizeof(receive_edid));
+               edid_len = 0;
+       } else {
                memcpy(receive_edid, data, len);
+               edid_len = len;
+       }
        new_edid = true;
        return true;
 }
-EXPORT_SYMBOL(rx_set_receiver_edid);
+
+void rx_hdcp14_resume(void)
+{
+       hdcp22_kill_esm = 0;
+       extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 0);
+       hdmirx_wr_dwc(DWC_HDCP22_CONTROL,
+                               0x1000);
+       extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 1);
+       hpd_to_esm = 1;
+       rx_pr("hdcp14 on\n");
+}
 
 void rx_set_repeater_support(bool enable)
 {
-       downstream_rp_en = enable;
+       downstream_repeat_support = enable;
 }
 EXPORT_SYMBOL(rx_set_repeater_support);
 
@@ -224,7 +265,8 @@ bool rx_poll_dwc(uint16_t addr, uint32_t exp_data,
                        rd_data = hdmirx_rd_dwc(addr);
                }
        }
-       rx_pr("poll dwc cnt :%d\n", cnt);
+       if (log_level & VIDEO_LOG)
+               rx_pr("poll dwc cnt :%d\n", cnt);
        if (done == 0) {
                /* if(log_level & ERR_LOG) */
                rx_pr("poll dwc%x time-out!\n", addr);
@@ -237,9 +279,13 @@ bool rx_set_repeat_aksv(unsigned char *data, int len, int depth,
        bool dev_exceed, bool cascade_exceed)
 {
        int i;
-       /*rx_pr("set ksv list len:%d,depth:%d\n", len, depth);*/
-       if ((len == 0) || (data == 0) || (depth == 0))
+       bool ksvlist_ready = 0;
+
+       if ((data == 0) || (((depth == 0) || (len == 0))
+               && (!dev_exceed) && (!cascade_exceed)))
                return false;
+       rx_pr("set ksv list len:%d,depth:%d, exceed count:%d,cascade:%d\n",
+                                       len, depth, dev_exceed, cascade_exceed);
        /*set repeat depth*/
        if ((depth <= MAX_REPEAT_DEPTH) && (!cascade_exceed)) {
                hdmirx_wr_bits_dwc(DWC_HDCP_RPT_BSTATUS, MAX_CASCADE_EXCEEDED,
@@ -249,9 +295,10 @@ bool rx_set_repeat_aksv(unsigned char *data, int len, int depth,
        } else {
                hdmirx_wr_bits_dwc(DWC_HDCP_RPT_BSTATUS, MAX_CASCADE_EXCEEDED,
                1);
+               rx.hdcp.depth = 0;
        }
        /*set repeat count*/
-       if ((len <= MAX_REPEAT_COUNT) && (!dev_exceed)) {
+       if ((len <= HDCP14_KSV_MAX_COUNT) && (!dev_exceed)) {
                hdmirx_wr_bits_dwc(DWC_HDCP_RPT_BSTATUS, MAX_DEVS_EXCEEDED,
                0);
                rx.hdcp.count = len;
@@ -260,15 +307,19 @@ bool rx_set_repeat_aksv(unsigned char *data, int len, int depth,
        } else {
                hdmirx_wr_bits_dwc(DWC_HDCP_RPT_BSTATUS, MAX_DEVS_EXCEEDED,
                1);
+               rx.hdcp.count = 0;
        }
        /*set repeat status*/
-       if (rx.hdcp.count > 0) {
-               rx.hdcp.repeat = true;
-               hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL, REPEATER, 1);
-       } else {
-               rx.hdcp.repeat = false;
-               hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL, REPEATER, 0);
-       }
+       /* if (rx.hdcp.count > 0) {
+        *      rx.hdcp.repeat = true;
+        *      hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL, REPEATER, 1);
+        *} else {
+        *      rx.hdcp.repeat = false;
+        *      hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL, REPEATER, 0);
+        *}
+        */
+       ksvlist_ready = ((rx.hdcp.count > 0) && (rx.hdcp.depth > 0));
+       rx_pr("[RX]write ksv list count:%d\n", rx.hdcp.count);
        /*write ksv list to fifo*/
        for (i = 0; i < rx.hdcp.count; i++) {
                if (rx_poll_dwc(DWC_HDCP_RPT_CTRL, ~KSV_HOLD, KSV_HOLD,
@@ -279,10 +330,11 @@ bool rx_set_repeat_aksv(unsigned char *data, int len, int depth,
                                *(data + i*MAX_KSV_SIZE + 4));
                        hdmirx_wr_dwc(DWC_HDCP_RPT_KSVFIFO0,
                                *((uint32_t *)(data + i*MAX_KSV_SIZE)));
-                       rx_pr(
-                       "[RX]write ksv list index:%d, ksv hi:%#x, low:%#x\n",
+                       if (log_level & VIDEO_LOG)
+                               rx_pr(
+                               "[RX]write ksv list index:%d, ksv hi:%#x, low:%#x\n",
                                i, *(data + i*MAX_KSV_SIZE +
-                       4), *((uint32_t *)(data + i*MAX_KSV_SIZE)));
+                               4), *((uint32_t *)(data + i*MAX_KSV_SIZE)));
                } else {
                        return false;
                }
@@ -290,11 +342,12 @@ bool rx_set_repeat_aksv(unsigned char *data, int len, int depth,
        /* Wait for ksv_hold=0*/
        rx_poll_dwc(DWC_HDCP_RPT_CTRL, ~KSV_HOLD, KSV_HOLD, KSV_LIST_WR_TH);
        /*set ksv list ready*/
-       hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL, KSVLIST_READY,
-                                       (rx.hdcp.count > 0));
+       hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL, KSVLIST_READY, ksvlist_ready);
        /* Wait for HW completion of V value*/
-       rx_poll_dwc(DWC_HDCP_RPT_CTRL, FIFO_READY, FIFO_READY, KSV_V_WR_TH);
-       rx_pr("[RX]write Ready signal!\n");
+       if (ksvlist_ready)
+               rx_poll_dwc(DWC_HDCP_RPT_CTRL, FIFO_READY,
+                                               FIFO_READY, KSV_V_WR_TH);
+       rx_pr("[RX]write Ready signal!\n", ksvlist_ready);
 
        return true;
 }
@@ -308,35 +361,17 @@ void rx_set_repeat_signal(bool repeat)
 bool rx_set_receive_hdcp(unsigned char *data, int len, int depth,
        bool cas_exceed, bool devs_exceed)
 {
-       if ((data != 0) && (len != 0) && (len <= MAX_REPEAT_COUNT))
-               memcpy(receive_hdcp, data, len*MAX_KSV_SIZE);
-       rx_pr("receive ksv list len:%d,depth:%d,cas:%d,dev:%d\n", len,
-       depth, cas_exceed, devs_exceed);
-       hdcp_len = len;
-       hdcp_repeat_depth = depth;
-       rx.hdcp.cascade_exceed = cas_exceed;
-       rx.hdcp.dev_exceed = devs_exceed;
-
        return true;
 }
 EXPORT_SYMBOL(rx_set_receive_hdcp);
 
 void rx_repeat_hpd_state(bool plug)
 {
-       repeat_plug = plug;
 }
 EXPORT_SYMBOL(rx_repeat_hpd_state);
 
-void rx_repeat_hdcp_ver(int version)
-{
-
-}
-EXPORT_SYMBOL(rx_repeat_hdcp_ver);
-
 void rx_edid_physical_addr(int a, int b, int c, int d)
 {
-       up_phy_addr = ((d & 0xf) << 12)  | ((c & 0xf) << 8) | ((b &
-       0xf) << 4) | (a & 0xf);
 }
 EXPORT_SYMBOL(rx_edid_physical_addr);
 
index 82340b4..da190fb 100644 (file)
 #define __HDMIRX_REPEATER__
 
 /* EDID */
-#define MAX_RECEIVE_EDID       33
+#define MAX_RECEIVE_EDID       40/*33*/
+#define MAX_HDR_LUMI           3
 #define MAX_KSV_SIZE           5
-#define MAX_REPEAT_COUNT       127
 #define MAX_REPEAT_DEPTH       7
-#define MAX_KSV_LIST_SIZE      (MAX_KSV_SIZE*MAX_REPEAT_COUNT)
+#define MAX_KSV_LIST_SIZE      sizeof(struct hdcp14_topo_s)
+#define HDCP14_KSV_MAX_COUNT   127
 #define DETAILED_TIMING_LEN    18
 /*size of one format in edid*/
 #define FORMAT_SIZE                    sizeof(struct edid_audio_block_t)
@@ -45,6 +46,22 @@ enum repeater_state_e {
        REPEATER_STATE_START,
 };
 
+struct hdcp14_topo_s {
+       unsigned char max_cascade_exceeded:1;
+       unsigned char depth:3;
+       unsigned char max_devs_exceeded:1;
+       unsigned char device_count:7; /* 1 ~ 127 */
+       unsigned char ksv_list[HDCP14_KSV_MAX_COUNT * 5];
+};
+
+struct hdcp_hw_info_s {
+       unsigned int cur_5v:4;
+       unsigned int open:4;
+       unsigned int frame_rate:8;
+       unsigned int signal_stable:1;
+       unsigned int reseved:15;
+};
+
 extern int receive_edid_len;
 extern bool new_edid;
 extern int hdcp_array_len;
@@ -53,15 +70,14 @@ extern int hdcp_repeat_depth;
 extern bool new_hdcp;
 extern bool repeat_plug;
 extern int up_phy_addr;/*d c b a 4bit*/
-extern bool downstream_rp_en;
 
-void rx_set_repeater_support(bool enable);
-extern int rx_set_receiver_edid(unsigned char *data, int len);
+extern void rx_set_repeater_support(bool enable);
+extern int rx_set_receiver_edid(const char *data, int len);
 extern void rx_start_repeater_auth(void);
 extern void rx_set_repeat_signal(bool repeat);
 extern bool rx_set_repeat_aksv(unsigned char *data, int len, int depth,
                bool dev_exceed, bool cascade_exceed);
-extern unsigned char *rx_get_receiver_edid(void);
+extern unsigned char *rx_get_dw_edid_addr(void);
 extern void repeater_dwork_handle(struct work_struct *work);
 bool rx_set_receive_hdcp(unsigned char *data,
        int len, int depth, bool cas_exceed, bool devs_exceed);
@@ -69,7 +85,10 @@ void rx_repeat_hpd_state(bool plug);
 void rx_repeat_hdcp_ver(int version);
 void rx_check_repeat(void);
 extern bool hdmirx_is_key_write(void);
-
+extern void rx_reload_firm_reset(int reset);
+extern void rx_firm_reset_end(void);
+extern unsigned char *rx_get_dw_hdcp_addr(void);
+extern unsigned char *rx_get_dw_edid_addr(void);
 
 
 #endif
index ecf4640..3429e37 100644 (file)
 #include <linux/amlogic/media/frame_provider/tvin/tvin.h>
 
 /* Local include */
+#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_drv.h"
 #include "hdmi_rx_hw.h"
 #include "hdmi_rx_eq.h"
 #include "hdmi_rx_wrapper.h"
 #include "hdmi_rx_pktinfo.h"
-#include "hdmi_rx_repeater.h"
 #include "hdmi_rx_edid.h"
 
 static int pll_unlock_cnt;
@@ -171,6 +171,10 @@ static bool mute_kill_en;
 MODULE_PARM_DESC(mute_kill_en, "\n mute_kill_en\n");
 module_param(mute_kill_en, bool, 0664);
 
+int hdcp14_on;
+MODULE_PARM_DESC(hdcp14_on, "\n hdcp14_on\n");
+module_param(hdcp14_on, int, 0664);
+
 /*esm recovery mode for changing resolution & hdmi2.0*/
 static int esm_recovery_mode = ESM_REC_MODE_TMDS;
 module_param(esm_recovery_mode, int, 0664);
@@ -190,6 +194,7 @@ static int edid_update_delay = 150;
 int skip_frame_cnt = 1;
 static bool hdcp22_reauth_enable;
 unsigned int edid_update_flag;
+unsigned int downstream_hpd_flag;
 static bool hdcp22_stop_auth_enable;
 static bool hdcp22_esm_reset2_enable;
 int sm_pause;
@@ -355,11 +360,8 @@ static int hdmi_rx_ctrl_irq_handler(void)
                        /*if (log_level & HDCP_LOG)*/
                        rx_pr("[*aksv*\n");
                        rx.hdcp.hdcp_version = HDCP_VER_14;
-                       if (hdmirx_repeat_support()) {
-                               queue_delayed_work(repeater_wq, &repeater_dwork,
-                                               msecs_to_jiffies(5));
+                       if (hdmirx_repeat_support())
                                rx_start_repeater_auth();
-                       }
                }
        }
 
@@ -1421,8 +1423,9 @@ void dump_unnormal_info(void)
 
 void rx_send_hpd_pulse(void)
 {
-       rx_set_cur_hpd(0);
-       fsm_restart();
+       /*rx_set_cur_hpd(0);*/
+       /*fsm_restart();*/
+       rx.state = FSM_HPD_LOW;
 }
 
 static void set_hdcp(struct hdmi_rx_hdcp *hdcp, const unsigned char *b_key)
@@ -1470,6 +1473,8 @@ void hdmirx_fill_key_buf(const char *buf, int size)
                //key_size = size;
                //rx_pr("HDMIRX: fill key buf, size %d\n", size);
        }
+       hdcp14_on = 1;
+       rx_pr("HDMIRX: fill key buf, hdcp14_on %d\n", hdcp14_on);
 }
 
 /*
@@ -1672,8 +1677,8 @@ int rx_set_global_variable(const char *buf, int size)
                return pr_var(dv_nopacket_timeout, index);
        if (set_pr_var(tmpbuf, delay_ms_cnt, value, &index, ret))
                return pr_var(delay_ms_cnt, index);
-       if (set_pr_var(tmpbuf, downstream_rp_en, value, &index, ret))
-               return pr_var(downstream_rp_en, index);
+       if (set_pr_var(tmpbuf, downstream_repeat_support, value, &index, ret))
+               return pr_var(downstream_repeat_support, index);
        if (set_pr_var(tmpbuf, eq_max_setting, value, &index, ret))
                return pr_var(eq_max_setting, index);
        if (set_pr_var(tmpbuf, eq_dbg_ch0, value, &index, ret))
@@ -1798,7 +1803,7 @@ void rx_get_global_variable(const char *buf)
        pr_var(hdcp22_on, i++);
        pr_var(dv_nopacket_timeout, i++);
        pr_var(delay_ms_cnt, i++);
-       pr_var(downstream_rp_en, i++);
+       pr_var(downstream_repeat_support, i++);
        pr_var(eq_max_setting, i++);
        pr_var(eq_dbg_ch0, i++);
        pr_var(eq_dbg_ch1, i++);
@@ -1952,6 +1957,7 @@ void rx_5v_monitor(void)
                rx.cur_5v_sts = (pwr_sts >> rx.port) & 1;
                hotplug_wait_query();
                if (rx.cur_5v_sts == 0) {
+                       /*External_Mute(1);*/
                        #ifdef USE_NEW_FSM_METHODE
                        set_fsm_state(FSM_5V_LOST);
                        rx.err_code = ERR_5V_LOST;
@@ -2101,12 +2107,18 @@ void rx_main_state_machine(void)
        case FSM_HPD_HIGH:
                hpd_wait_cnt++;
                if (rx_get_cur_hpd_sts() == 0) {
-                       if (hpd_wait_cnt <= hpd_wait_max)
-                               break;
+                       if (downstream_hpd_flag) {
+                               if (hpd_wait_cnt <= hpd_wait_max*5)
+                                       break;
+                       } else {
+                               if (hpd_wait_cnt <= hpd_wait_max)
+                                       break;
+                       }
                }
                hpd_wait_cnt = 0;
                clk_unstable_cnt = 0;
                esd_phy_rst_cnt = 0;
+               downstream_hpd_flag = 0;
                pre_port = rx.port;
                rx_set_cur_hpd(1);
                set_scdc_cfg(0, 1);
@@ -2339,6 +2351,7 @@ void rx_main_state_machine(void)
                        rx.aud_sr_unstable_cnt++;
                        if (rx.aud_sr_unstable_cnt > aud_sr_stb_max) {
                                unsigned int aud_sts = rx_get_aud_pll_err_sts();
+
                                if (aud_sts == E_REQUESTCLK_ERR) {
                                        hdmirx_phy_init();
                                        rx.state = FSM_WAIT_CLK_STABLE;
@@ -2381,9 +2394,6 @@ void rx_main_state_machine(void)
 
        if (log_level & VIDEO_LOG)
                rx_esm_exception_monitor();/* only for debug */
-       if ((hdcp22_on) && (rx.state > FSM_SIG_UNSTABLE)) {
-               /*monitor_hdcp22_sts();*/
-       }
 
        switch (rx.state) {
        case FSM_HPD_LOW:
@@ -3025,7 +3035,7 @@ int hdmirx_debug(const char *buf, int size)
        } else if (strncmp(tmpbuf, "reg", 3) == 0) {
                dump_reg();
        }  else if (strncmp(tmpbuf, "duk", 3) == 0) {
-               rx_pr("hdcp22=%d\n", rx_sec_set_duk());
+               rx_pr("hdcp22=%d\n", rx_sec_set_duk(hdmirx_repeat_support()));
        } else if (strncmp(tmpbuf, "edid", 4) == 0) {
                dump_edid_reg();
        } else if (strncmp(tmpbuf, "load14key", 7) == 0) {
@@ -3080,6 +3090,8 @@ int hdmirx_debug(const char *buf, int size)
                        rx_pr("error input Value\n");
                rx_pr("set pkt cnt:0x%x\n", value);
                rx.empbuff.emppktcnt = value;
+       } else if (strncmp(tmpbuf, "audio", 5) == 0) {
+               hdmirx_audio_fifo_rst();
        }
 
        return 0;
@@ -3092,14 +3104,16 @@ void hdmirx_timer_handler(unsigned long arg)
        rx_5v_monitor();
        rx_check_repeat();
        if (rx.open_fg) {
-               if (!sm_pause)
-                       rx_main_state_machine();
                rx_nosig_monitor();
-               rx_pkt_check_content();
-               #ifdef USE_NEW_FSM_METHODE
-               rx_err_monitor();
-               rx_clkrate_monitor();
-               #endif
+               if (!hdmirx_repeat_support() || !rx.firm_change) {
+                       if (!sm_pause)
+                               rx_main_state_machine();
+                       rx_pkt_check_content();
+                       #ifdef USE_NEW_FSM_METHODE
+                       rx_err_monitor();
+                       rx_clkrate_monitor();
+                       #endif
+               }
        }
        devp->timer.expires = jiffies + TIMER_STATE_CHECK;
        add_timer(&devp->timer);