hdmirx: add hdmi plug & cec rx msg uevent [1/1]
authorhang cheng <hang.cheng@amlogic.com>
Sat, 8 May 2021 10:16:59 +0000 (18:16 +0800)
committerChristian Hoffmann <chrmhoffmann@gmail.com>
Sun, 12 Feb 2023 08:13:11 +0000 (09:13 +0100)
PD#SWPL-47310

Problem:
1.need hdmi plug uevent to check connection status
2.need cec rx msg uevent instead of poll
3.hdmitx hdcp result for uevent is wrong

Solution:
1.add hdmitx/rx hotplug & cec rx msg uevent
2.correct hdcp result for drm uevent

Verify:
ab311

Change-Id: I60bc0e869770965df676ff22801ee1ff7981916b
Signed-off-by: hang cheng <hang.cheng@amlogic.com>
drivers/amlogic/cec/hdmi_ao_cec.c
drivers/amlogic/cec/hdmi_ao_cec.h
drivers/amlogic/drm/meson_hdmi.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv_ext.h [new file with mode: 0644]
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_hdcp.c
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main_drm.c
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c
include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h

index 5e034488ad5ebad32dfdd8ef2a7af77c68b5a74d..2d10717db4dadf736665174fa72cd9df247b8f88 100644 (file)
 #include <linux/poll.h>
 #include <linux/amlogic/media/frame_provider/tvin/tvin.h>
 #include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h>
+#ifdef CONFIG_AMLOGIC_HDMITX
 #include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
+#endif
 #include <linux/amlogic/pm.h>
 #include <linux/amlogic/cpu_version.h>
 #include <linux/amlogic/jtag.h>
 #include <linux/amlogic/scpi_protocol.h>
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
+#include "../media/vin/tvin/hdmirx/hdmi_rx_drv_ext.h"
+#endif
 
 #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
 static struct early_suspend aocec_suspend_handler;
@@ -259,6 +264,27 @@ unsigned int read_clock(unsigned int addr)
        return data;
 }
 
+static struct cec_uevent cec_events[] = {
+       {
+               .type = HDMI_PLUG_EVENT,
+               .env = "hdmi_conn=",
+       },
+       {
+               .type = CEC_RX_MSG,
+               .env = "cec_rx_msg=",
+       },
+       {
+               /* end of cec_events[] */
+               .type = CEC_NONE_EVENT,
+       }
+};
+
+static int hdmitx_notify_callback(struct notifier_block *block,
+                                 unsigned long cmd, void *para);
+static struct notifier_block hdmitx_notifier_nb = {
+       .notifier_call  = hdmitx_notify_callback
+};
+
 unsigned int waiting_aocec_free(unsigned int r)
 {
        unsigned int cnt = 0;
@@ -3578,6 +3604,9 @@ void cec_new_msg_push(void)
                complete(&cec_dev->rx_ok);
                new_msg = 1;
                wake_up(&cec_msg_wait_queue);
+               /* uevent to notify cec msg received */
+               queue_delayed_work(cec_dev->cec_rx_event_wq,
+                                  &cec_dev->work_cec_rx, 0);
        }
 }
 
@@ -3926,6 +3955,111 @@ static void cec_get_wakeup_data(void)
                *((unsigned int *)&cec_dev->wakup_data));
 }
 
+int cec_set_uevent(enum cec_event_type type, unsigned int val)
+{
+       char env[MAX_UEVENT_LEN];
+       struct cec_uevent *event = cec_events;
+       char *envp[2];
+       int ret = -1;
+
+       /* hdmi_plug/cec_rx uevent may concurrent, need mutex */
+       mutex_lock(&cec_dev->cec_uevent_mutex);
+       for (event = cec_events; event->type != CEC_NONE_EVENT; event++) {
+               if (type == event->type)
+                       break;
+       }
+       if (event->type == CEC_NONE_EVENT) {
+               CEC_ERR("[%s] unsupported event:0x%x\n", __func__, type);
+               mutex_unlock(&cec_dev->cec_uevent_mutex);
+               return ret;
+       }
+       if (event->state == val) {
+               CEC_INFO("[%s] state not chg:0x%x\n", __func__, val);
+               mutex_unlock(&cec_dev->cec_uevent_mutex);
+               return ret;
+       }
+       event->state = val;
+       memset(env, 0, sizeof(env));
+       envp[0] = env;
+       envp[1] = NULL;
+       snprintf(env, MAX_UEVENT_LEN, "%s%x", event->env, val);
+
+       ret = kobject_uevent_env(&cec_dev->dbg_dev->kobj, KOBJ_CHANGE, envp);
+       CEC_INFO("[%s] %s %d\n", __func__, env, ret);
+       mutex_unlock(&cec_dev->cec_uevent_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL(cec_set_uevent);
+
+/* handler for both hdmitx & rx */
+static void cec_hdmi_plug_handler(struct work_struct *work)
+{
+       /* struct ao_cec_dev *pcec_dev = */
+               /* container_of((struct delayed_work *)work, */
+               /* struct ao_cec_dev, work_hdmitx_plug); */
+       unsigned int tmp = 0;
+
+#ifdef CONFIG_AMLOGIC_HDMITX
+       tmp |= (cec_dev->tx_dev->hpd_state << 4);
+#endif
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
+       tmp |= (hdmirx_get_connect_info() & 0xF);
+#endif
+
+       cec_set_uevent(HDMI_PLUG_EVENT, tmp);
+}
+
+static void cec_rx_uevent_handler(struct work_struct *work)
+{
+       /* struct ao_cec_dev *pcec_dev = */
+               /* container_of((struct delayed_work *)work, */
+               /* struct ao_cec_dev, work_cec_rx); */
+       /* notify framework to read cec msg */
+       cec_set_uevent(CEC_RX_MSG, 1);
+       /* clear notify */
+       cec_set_uevent(CEC_RX_MSG, 0);
+}
+
+static int hdmitx_notify_callback(struct notifier_block *block,
+                                 unsigned long cmd, void *para)
+{
+       int ret = 0;
+
+       switch (cmd) {
+#ifdef CONFIG_AMLOGIC_HDMITX
+       case HDMITX_PLUG:
+       case HDMITX_UNPLUG:
+               CEC_INFO("[%s] event: %ld\n", __func__, cmd);
+               queue_delayed_work(cec_dev->hdmi_plug_wq,
+                                  &cec_dev->work_hdmi_plug, 0);
+               break;
+#endif
+       default:
+               CEC_ERR("[%s] unsupported notify:%ld\n", __func__, cmd);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
+static int hdmirx_notify_callback(unsigned int pwr5v_sts)
+{
+       int ret = 0;
+       unsigned int tmp = 0;
+
+#ifdef CONFIG_AMLOGIC_HDMITX
+       tmp |= (cec_dev->tx_dev->hpd_state << 4);
+#endif
+       tmp |= (pwr5v_sts & 0xF);
+
+       queue_delayed_work(cec_dev->hdmi_plug_wq, &cec_dev->work_hdmi_plug, 0);
+
+       return ret;
+}
+#endif
+
 static int aml_cec_probe(struct platform_device *pdev)
 {
        struct device *cdev;
@@ -3999,6 +4133,7 @@ static int aml_cec_probe(struct platform_device *pdev)
        init_completion(&cec_dev->tx_ok);
        mutex_init(&cec_dev->cec_tx_mutex);
        mutex_init(&cec_dev->cec_ioctl_mutex);
+       mutex_init(&cec_dev->cec_uevent_mutex);
        spin_lock_init(&cec_dev->cec_reg_lock);
        cec_dev->cec_info.remote_cec_dev = input_allocate_device();
        if (!cec_dev->cec_info.remote_cec_dev) {
@@ -4286,6 +4421,26 @@ static int aml_cec_probe(struct platform_device *pdev)
                ret = -EFAULT;
                goto tag_cec_threat_err;
        }
+       /* for hdmitx/rx plug uevent report */
+       cec_dev->hdmi_plug_wq =
+               alloc_workqueue("cec_hdmi_plug",
+                               WQ_HIGHPRI | WQ_CPU_INTENSIVE, 0);
+       if (!cec_dev->hdmi_plug_wq) {
+               CEC_INFO("create hdmi_plug_wq failed\n");
+               ret = -EFAULT;
+               goto tag_hdmi_plug_wq_err;
+       }
+       INIT_DELAYED_WORK(&cec_dev->work_hdmi_plug, cec_hdmi_plug_handler);
+       /* for cec rx msg uevent report */
+       cec_dev->cec_rx_event_wq =
+               alloc_workqueue("cec_rx_event",
+                               WQ_HIGHPRI | WQ_CPU_INTENSIVE, 0);
+       if (!cec_dev->cec_rx_event_wq) {
+               CEC_INFO("create cec_rx_event_wq failed\n");
+               ret = -EFAULT;
+               goto tag_cec_rx_event_wq_err;
+       }
+       INIT_DELAYED_WORK(&cec_dev->work_cec_rx, cec_rx_uevent_handler);
        /*freeze wakeup init*/
        device_init_wakeup(&pdev->dev, 1);
        /*CEC_INFO("dev init wakeup\n");*/
@@ -4303,12 +4458,26 @@ static int aml_cec_probe(struct platform_device *pdev)
        queue_delayed_work(cec_dev->cec_thread, &cec_dev->cec_work, 0);
        tasklet_init(&ceca_tasklet, ceca_tasklet_pro,
                (unsigned long)cec_dev);
+#ifdef CONFIG_AMLOGIC_HDMITX
+       hdmitx_event_notifier_regist(&hdmitx_notifier_nb);
+#endif
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
+       register_cec_callback(hdmirx_notify_callback);
+#endif
        cec_get_wakeup_reason();
        cec_get_wakeup_data();
        cec_irq_enable(true);
        cec_dev->probe_finish = true;
        return 0;
 
+tag_cec_rx_event_wq_err:
+       destroy_workqueue(cec_dev->hdmi_plug_wq);
+tag_hdmi_plug_wq_err:
+       destroy_workqueue(cec_dev->cec_thread);
+tag_cec_threat_err:
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       unregister_early_suspend(&aocec_suspend_handler);
+#endif
 tag_cec_msg_alloc_err:
        if (cec_dev->cec_num > ENABLE_ONE_CEC) {
                free_irq(cec_dev->irq_ceca, (void *)cec_dev);
@@ -4322,10 +4491,7 @@ tag_cec_msg_alloc_err:
 tag_cec_reg_map_err:
        input_free_device(cec_dev->cec_info.remote_cec_dev);
 tag_cec_alloc_input_err:
-       destroy_workqueue(cec_dev->cec_thread);
-tag_cec_threat_err:
-       device_destroy(&aocec_class,
-               MKDEV(cec_dev->cec_info.dev_no, 0));
+       device_destroy(&aocec_class, MKDEV(cec_dev->cec_info.dev_no, 0));
 tag_cec_device_create_err:
        unregister_chrdev(cec_dev->cec_info.dev_no, CEC_DEV_NAME);
 tag_cec_chr_reg_err:
@@ -4355,6 +4521,20 @@ static int aml_cec_remove(struct platform_device *pdev)
                cancel_delayed_work_sync(&cec_dev->cec_work);
                destroy_workqueue(cec_dev->cec_thread);
        }
+#ifdef CONFIG_AMLOGIC_HDMITX
+       hdmitx_event_notifier_unregist(&hdmitx_notifier_nb);
+#endif
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
+       unregister_cec_callback();
+#endif
+       if (cec_dev->hdmi_plug_wq) {
+               cancel_delayed_work_sync(&cec_dev->work_hdmi_plug);
+               destroy_workqueue(cec_dev->hdmi_plug_wq);
+       }
+       if (cec_dev->cec_rx_event_wq) {
+               cancel_delayed_work_sync(&cec_dev->work_cec_rx);
+               destroy_workqueue(cec_dev->cec_rx_event_wq);
+       }
        input_unregister_device(cec_dev->cec_info.remote_cec_dev);
        unregister_chrdev(cec_dev->cec_info.dev_no, CEC_DEV_NAME);
        class_unregister(&aocec_class);
index 3a956117d83ca687fc444ce33a911b00d82fdc0a..d0ffba1276babd0cf4f489573b077d34319afe01 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef __AO_CEC_H__
 #define __AO_CEC_H__
 
-#define CEC_DRIVER_VERSION     "2021/01/19:phy addr error, defaut is 0xffff"
+#define CEC_DRIVER_VERSION     "2021/05/14: hdmi plug & cec rx msg uevent"
 
 #define CEC_DEV_NAME           "cec"
 
@@ -165,14 +165,19 @@ struct ao_cec_dev {
        void __iomem *clk_reg;
        struct hdmitx_dev *tx_dev;
        struct workqueue_struct *cec_thread;
+       struct workqueue_struct *hdmi_plug_wq;
+       struct workqueue_struct *cec_rx_event_wq;
        struct device *dbg_dev;
        const char *pin_name;
        struct delayed_work cec_work;
+       struct delayed_work work_hdmi_plug;
+       struct delayed_work work_cec_rx;
        struct completion rx_ok;
        struct completion tx_ok;
        spinlock_t cec_reg_lock;/*cec register access*/
        struct mutex cec_tx_mutex;/*pretect tx cec msg*/
        struct mutex cec_ioctl_mutex;
+       struct mutex cec_uevent_mutex; /* cec uevent */
        struct cec_wakeup_t wakup_data;
        unsigned int wakeup_reason;
 #ifdef CONFIG_PM
@@ -507,6 +512,20 @@ enum {
        CECB_STAT0_P2S_FBACK_RX_ERR = 6,
 };
 
+enum cec_event_type {
+       CEC_NONE_EVENT = 0,
+       HDMI_PLUG_EVENT = 1,
+       CEC_RX_MSG = 2
+};
+
+#define MAX_UEVENT_LEN 64
+
+struct cec_uevent {
+       enum cec_event_type type;
+       unsigned int state;
+       const char *env;
+};
+
 /* cec ip irq flags bit discription */
 #define EECEC_IRQ_TX_DONE                      BIT(16)
 #define EECEC_IRQ_RX_EOM                       BIT(17)
index 06eea1a8ac2b4353acc195bd2ac469e00b3ed2af..edd5bfffb1f97e09f899fb40552fa1e8b87f6ee0 100644 (file)
@@ -1291,7 +1291,11 @@ static irqreturn_t am_hdmi_irq(int irq, void *dev_id)
                        hdmi_tx_edid_proc((unsigned char *)edid);
                        kfree(edid);
                }
+               hdmitx_dev->hpd_state = 1;
+       } else if (am_hdmi->hpd_flag == 2) {
+               hdmitx_dev->hpd_state = 0;
        }
+       hdmitx_notify_hpd(hdmitx_dev->hpd_state, NULL);
        drm_helper_hpd_irq_event(am_hdmi->connector.dev);
        return IRQ_HANDLED;
 }
@@ -1457,6 +1461,10 @@ void am_hdmitx_hdcp_result(unsigned int *exe_type,
        *result_type = (unsigned int)am_hdmi_info.hdcp_result;
 }
 
+void am_hdmitx_set_hdcp_mode(unsigned int user_type)
+{
+       am_hdmi_info.hdcp_user_type = user_type;
+}
 static int am_meson_hdmi_probe(struct platform_device *pdev)
 {
        struct hdmitx_dev *hdmitx_dev;
@@ -1468,6 +1476,7 @@ static int am_meson_hdmi_probe(struct platform_device *pdev)
        hdmitx_dev->hwop.am_hdmitx_hdcp_disable = am_hdmitx_hdcp_disable;
        hdmitx_dev->hwop.am_hdmitx_hdcp_enable = am_hdmitx_hdcp_enable;
        hdmitx_dev->hwop.am_hdmitx_hdcp_result = am_hdmitx_hdcp_result;
+       hdmitx_dev->hwop.am_hdmitx_set_hdcp_mode = am_hdmitx_set_hdcp_mode;
        return component_add(&pdev->dev, &am_meson_hdmi_ops);
 }
 
index 773f49a1f697fe8b6c1cbb37cb9b68f65d198789..15173b93ac83048ee81b1db356341a64f499ff50 100644 (file)
@@ -15,8 +15,8 @@
  *
  */
 
-#ifndef _TVHDMI_H
-#define _TVHDMI_H
+#ifndef __HDMI_RX_DRV_H__
+#define __HDMI_RX_DRV_H__
 
 #include <linux/workqueue.h>
 #include <linux/extcon.h>
@@ -32,7 +32,7 @@
 //#include "hdmirx_repeater.h"
 //#include "hdmi_rx_pktinfo.h"
 #include "hdmi_rx_edid.h"
-
+#include "hdmi_rx_drv_ext.h"
 
 #define RX_VER0 "ver.2019/10/21"
 /*
@@ -47,7 +47,7 @@
  *
  *
  */
-#define RX_VER2 "ver.2019/11/18"
+#define RX_VER2 "ver.2021/05/14"
 
 /*print type*/
 #define        LOG_EN          0x01
@@ -483,7 +483,6 @@ 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);
-extern int cec_set_dev_info(uint8_t dev_idx);
 
 /* reg */
 
@@ -563,5 +562,4 @@ extern unsigned int *pd_fifo_buf;
 /* for other modules */
 extern int External_Mute(int mute_flag);
 extern int rx_is_hdcp22_support(void);
-extern int hdmirx_get_connect_info(void);
 #endif
diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv_ext.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv_ext.h
new file mode 100644 (file)
index 0000000..f200528
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __HDMI_RX_DRV_EXT_H__
+#define __HDMI_RX_DRV_EXT_H__
+
+/* for CEC notify */
+typedef int (*cec_callback)(unsigned int pwr5v_sts);
+
+int hdmirx_get_connect_info(void);
+int cec_set_dev_info(u8 dev_idx);
+/* int hdmirx_set_cec_cfg(u32 cfg); */
+int register_cec_callback(cec_callback callback);
+void unregister_cec_callback(void);
+
+#endif
index c6a5876e8dd77dbe043cb6714d40c0ce750b31ee..aa3d837199df5d790cf77aa00d01f48295882da6 100644 (file)
@@ -45,6 +45,7 @@
 #include "hdmi_rx_wrapper.h"
 #include "hdmi_rx_pktinfo.h"
 #include "hdmi_rx_edid.h"
+#include "hdmi_rx_drv_ext.h"
 
 static int pll_unlock_cnt;
 static int pll_unlock_max = 30;
@@ -208,6 +209,7 @@ static int esd_phy_rst_cnt;
 static int esd_phy_rst_max;
 static int cec_dev_info;
 struct rx_s rx;
+static cec_callback cec_hdmirx5v_update;
 
 void hdmirx_init_params(void)
 {
@@ -247,6 +249,19 @@ int cec_set_dev_info(uint8_t dev_idx)
 }
 EXPORT_SYMBOL(cec_set_dev_info);
 
+int register_cec_callback(cec_callback callback)
+{
+       cec_hdmirx5v_update = callback;
+       return 0;
+}
+EXPORT_SYMBOL(register_cec_callback);
+
+void unregister_cec_callback(void)
+{
+       cec_hdmirx5v_update = NULL;
+}
+EXPORT_SYMBOL(unregister_cec_callback);
+
 /*
  *func: irq tasklet
  *param: flag:
@@ -1989,6 +2004,8 @@ void rx_5v_monitor(void)
                check_cnt = 0;
                pwr_sts = tmp_5v;
                rx.cur_5v_sts = (pwr_sts >> rx.port) & 1;
+               if (cec_hdmirx5v_update)
+                       cec_hdmirx5v_update(pwr_sts);
                hotplug_wait_query();
                rx_pr("hotplug-0x%x\n", pwr_sts);
                if (rx.cur_5v_sts == 0) {
index 232e16bb88a65f6c9b31ce4fc2d9534253e228b1..19fea697ae6fa75c3f9efb7f94d1c29b3cabe15f 100644 (file)
@@ -203,15 +203,23 @@ static int hdmitx_hdcp_task(void *data)
 {
        static int auth_trigger;
        struct hdmitx_dev *hdev = (struct hdmitx_dev *)data;
+       unsigned int hdcp_mode;
 
        INIT_DELAYED_WORK(&hdev->work_do_hdcp, _hdcp_do_work);
        while (hdev->hpd_event != 0xff) {
-               hdmi_authenticated = hdev->hwop.cntlddc(hdev,
-                       DDC_HDCP_GET_AUTH, 0);
+               if (hdev->drm_feature) {
+                       if (hdev->hwop.am_hdmitx_hdcp_result)
+                               hdev->hwop.am_hdmitx_hdcp_result(&hdcp_mode,
+                               &hdmi_authenticated);
+               } else {
+                       hdmi_authenticated = hdev->hwop.cntlddc(hdev,
+                               DDC_HDCP_GET_AUTH, 0);
+                       hdcp_mode = hdev->hdcp_mode;
+               }
                hdmitx_hdcp_status(hdmi_authenticated);
                if (auth_trigger != hdmi_authenticated) {
                        auth_trigger = hdmi_authenticated;
-                       pr_info("hdcptx: %d  auth: %d\n", hdev->hdcp_mode,
+                       pr_info("hdcptx: %d  auth: %d\n", hdcp_mode,
                                auth_trigger);
                }
                msleep_interruptible(200);
index ac67a30ff007011bbaa34a372807fd808289ac88..88ee929e9ad49a77e847012fe0a7ac6e22a8f385 100644 (file)
@@ -455,13 +455,15 @@ struct extcon_dev *hdmitx_extcon_cedst;
  * are remained the same. So, add hdr_status_pos and place it in the above 3
  * functions to record the position.
  */
-static inline void hdmitx_notify_hpd(int hpd, void *p)
+void hdmitx_notify_hpd(int hpd, void *p)
 {
        if (hpd)
                hdmitx_event_notify(HDMITX_PLUG, p);
        else
                hdmitx_event_notify(HDMITX_UNPLUG, NULL);
 }
+EXPORT_SYMBOL(hdmitx_notify_hpd);
+
 
 #if defined(CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND) && !defined(CONFIG_AMLOGIC_DRM)
 #include <linux/amlogic/pm.h>
index 8b0eb3da312a1c62b0bc85905b2803a77565fb54..1ce6e5a9b4ead2cc0cb96a025ecd10e3dc18cb96 100644 (file)
@@ -3388,6 +3388,11 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf)
                }
        } else if (strncmp(tmpbuf, "stop_vsif", 9) == 0) {
                hdmitx_disable_packet(HDMI_PACKET_VEND);
+       } else if (strncmp(tmpbuf, "hdcp_mode", 9) == 0) {
+               ret = kstrtoul(tmpbuf + 9, 16, &value);
+               if ((value >= 0) && (value <= 3) &&
+                       hdev->hwop.am_hdmitx_set_hdcp_mode)
+                       hdev->hwop.am_hdmitx_set_hdcp_mode(value);
        }
 }
 
index 74046ebd891e59c93f70f23fc441439d2fb6bdc6..ec507f399edff168e22a60705ce68e4a8a0f1f22 100644 (file)
@@ -387,6 +387,7 @@ struct hdmitx_dev {
                void (*am_hdmitx_hdcp_enable)(void);
                void (*am_hdmitx_hdcp_result)(unsigned int *exe_type,
                                unsigned int *result_type);
+               void (*am_hdmitx_set_hdcp_mode)(unsigned int user_type);
        } hwop;
        struct {
                unsigned int hdcp14_en;
@@ -798,6 +799,9 @@ int hdmitx_set_uevent(enum hdmitx_event type, int val);
 #ifdef CONFIG_AMLOGIC_HDMITX
 extern struct hdmitx_dev *get_hdmitx_device(void);
 extern int get_hpd_state(void);
+#ifdef CONFIG_DRM_MESON_HDMI
+void hdmitx_notify_hpd(int hpd, void *p);
+#endif
 bool is_tv_changed(void);
 extern int hdmitx_event_notifier_regist(struct notifier_block *nb);
 extern int hdmitx_event_notifier_unregist(struct notifier_block *nb);