summaryrefslogtreecommitdiff
authorXindong Xu <xindong.xu@amlogic.com>2018-03-09 02:51:04 (GMT)
committer Xindong Xu <xindong.xu@amlogic.com>2018-03-09 04:51:36 (GMT)
commitf147474d83e57cab17e523e2d5b2a3856ef97778 (patch)
tree33160f25d9b0489cd955af31e44d91cb55fdf051
parent48adbd18aaacf17714bb5026e20949a13f6584db (diff)
downloadcommon-f147474d83e57cab17e523e2d5b2a3856ef97778.zip
common-f147474d83e57cab17e523e2d5b2a3856ef97778.tar.gz
common-f147474d83e57cab17e523e2d5b2a3856ef97778.tar.bz2
cec: merge cec from trunk [1/1]
PD# NONE merge cec from trunk Change-Id: I65944fe77b1d4c3f0d58777fec881648fa7f8abc
Diffstat
-rw-r--r--arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts4
-rw-r--r--arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts4
-rw-r--r--drivers/amlogic/cec/hdmi_ao_cec.c1774
-rw-r--r--drivers/amlogic/cec/hdmi_ao_cec.h360
-rw-r--r--include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h6
7 files changed, 1431 insertions, 725 deletions
diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts
index ee8111e..7565ddc 100644
--- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts
+++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts
@@ -606,12 +606,12 @@
status = "okay";
vendor_id = <0x000000>;
cec_osd_string = "MBox"; /* Max Chars: 14 */
- cec_version = <6>; /* 5: 1.4, 6: 2.0 */
+ cec_version = <5>; /* 5: 1.4, 6: 2.0 */
port_num = <1>;
arc_port_mask = <0x0>;
interrupts = <0 199 1>;
interrupt-names = "hdmi_aocec";
- pinctrl-names = "hdmitx_aocec";
+ pinctrl-names = "default";
pinctrl-0=<&hdmitx_aocec>;
reg = <0x0 0xc810023c 0x0 0x4
0x0 0xc8100000 0x0 0x200>;
diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts
index 2f0c547..f105eab 100644
--- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts
+++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts
@@ -703,12 +703,12 @@
status = "okay";
vendor_id = <0x000000>;
cec_osd_string = "MBox"; /* Max Chars: 14 */
- cec_version = <6>; /* 5: 1.4, 6: 2.0 */
+ cec_version = <5>; /* 5: 1.4, 6: 2.0 */
port_num = <1>;
arc_port_mask = <0x0>;
interrupts = <0 199 1>;
interrupt-names = "hdmi_aocec";
- pinctrl-names = "hdmitx_aocec";
+ pinctrl-names = "default";
pinctrl-0=<&hdmitx_aocec>;
reg = <0x0 0xc810023c 0x0 0x4
0x0 0xc8100000 0x0 0x200>;
diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts
index 46f128b..18ea849 100644
--- a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts
+++ b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts
@@ -619,12 +619,12 @@
status = "okay";
vendor_id = <0x000000>;
cec_osd_string = "MBox"; /* Max Chars: 14 */
- cec_version = <6>; /* 5: 1.4, 6: 2.0 */
+ cec_version = <5>; /* 5: 1.4, 6: 2.0 */
port_num = <1>;
arc_port_mask = <0x0>;
interrupts = <0 199 1>;
interrupt-names = "hdmi_aocec";
- pinctrl-names = "hdmitx_aocec";
+ pinctrl-names = "default";
pinctrl-0=<&hdmitx_aocec>;
reg = <0x0 0xc810023c 0x0 0x4
0x0 0xc8100000 0x0 0x200>;
diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts
index 46ad8ae..aa2edd7 100644
--- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts
+++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts
@@ -619,12 +619,12 @@
status = "okay";
vendor_id = <0x000000>;
cec_osd_string = "MBox"; /* Max Chars: 14 */
- cec_version = <6>; /* 5: 1.4, 6: 2.0 */
+ cec_version = <5>; /* 5: 1.4, 6: 2.0 */
port_num = <1>;
arc_port_mask = <0x0>;
interrupts = <0 199 1>;
interrupt-names = "hdmi_aocec";
- pinctrl-names = "hdmitx_aocec";
+ pinctrl-names = "default";
pinctrl-0=<&hdmitx_aocec>;
reg = <0x0 0xc810023c 0x0 0x4
0x0 0xc8100000 0x0 0x200>;
diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c
index 39f051f..baad0cf 100644
--- a/drivers/amlogic/cec/hdmi_ao_cec.c
+++ b/drivers/amlogic/cec/hdmi_ao_cec.c
@@ -8,13 +8,14 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
*/
+#include <asm/irq.h>
+
#include <linux/version.h>
#include <linux/module.h>
#include <linux/irq.h>
@@ -23,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/delay.h>
+#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/init.h>
@@ -32,119 +34,127 @@
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/cdev.h>
-#include <asm/irq.h>
#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/spinlock_types.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
-
-#include <linux/uaccess.h>
-#include <linux/delay.h>
-
-#include <linux/amlogic/pm.h>
+#include <linux/atomic.h>
#include <linux/of.h>
-#include <linux/pinctrl/consumer.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include "hdmi_ao_cec.h"
-#include <linux/notifier.h>
#include <linux/reboot.h>
-#include <linux/of_address.h>
+#include <linux/notifier.h>
#include <linux/random.h>
-#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
+#include <linux/pinctrl/consumer.h>
+
+#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
+#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h>
+#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
#include <linux/amlogic/pm.h>
-#endif
#include <linux/amlogic/cpu_version.h>
-#include <linux/amlogic/cec_common.h>
-#include <linux/notifier.h>
+#include <linux/amlogic/jtag.h>
-#ifdef CONFIG_AMLOGIC_HDMITX
-#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+static struct early_suspend aocec_suspend_handler;
#endif
-#define DEFAULT_DEBUG_EN 0
+#include "hdmi_ao_cec.h"
+
+
+#define CEC_FRAME_DELAY msecs_to_jiffies(400)
+#define CEC_DEV_NAME "cec"
+
+#define DEV_TYPE_TV 0
+#define DEV_TYPE_RECORDER 1
+#define DEV_TYPE_RESERVED 2
+#define DEV_TYPE_TUNER 3
+#define DEV_TYPE_PLAYBACK 4
+#define DEV_TYPE_AUDIO_SYSTEM 5
+#define DEV_TYPE_PURE_CEC_SWITCH 6
+#define DEV_TYPE_VIDEO_PROCESSOR 7
+
+#define CEC_POWER_ON (0 << 0)
+#define CEC_EARLY_SUSPEND (1 << 0)
+#define CEC_DEEP_SUSPEND (1 << 1)
+#define CEC_POWER_RESUME (1 << 2)
-#define DBG_BUF_SIZE 80
-#define MAX_INT 0x7ffffff
+#define HR_DELAY(n) (ktime_set(0, n * 1000 * 1000))
+#define MAX_INT 0x7ffffff
+
+struct cec_platform_data_s {
+ unsigned int line_bit;/*cec gpio position in reg*/
+ bool ee_to_ao;/*ee cec hw module mv to ao;ao cec delete*/
+};
/* global struct for tx and rx */
struct ao_cec_dev {
- unsigned char rx_msg[MAX_MSG];
- /* bit filed for flags */
- struct {
- unsigned char my_log_addr : 4;
- unsigned char port_num : 4; /* first bytes */
- unsigned char cec_tx_result : 2;
- unsigned char power_status : 2;
- unsigned char rx_len : 4; /* second bytes */
- #ifdef CONFIG_PM
- unsigned char cec_suspend : 2;
- #endif
- unsigned char dev_type : 3;
- unsigned char cec_version : 3; /* third bytes */
- /* remaining bool flags */
- bool new_msg : 1;
- bool phy_addr_test : 1;
- bool wake_ok : 1;
- bool ee_cec : 1;
- bool cec_msg_dbg_en : 1;
- bool hal_control : 1;
- /*
- * pin_status: tv support cec check, for box
- * hpd_state: hdmi cable connected status
- *
- * hpd_state pin_status | TV support cec
- * 0 x | N/A
- * 1 0 | 0
- * 1 1 | 1
- */
- bool pin_status : 1;
- bool hpd_state : 1;
- };
-
- /* hardware config */
- unsigned short arc_port;
- unsigned short phy_addr;
- unsigned short irq_cec;
- unsigned short cec_line_cnt;
- unsigned short hal_flag;
- unsigned int port_seq;
-
- /* miscellaneous */
- unsigned int menu_lang;
- unsigned int open_count;
- dev_t dev_no;
-
- /* vendor related */
- unsigned int vendor_id;
- char *osd_name;
- char *product;
- const char *pin_name;
-
- /* resource of register */
+ unsigned long dev_type;
+ unsigned int port_num;
+ unsigned int arc_port;
+ unsigned int hal_flag;
+ unsigned int phy_addr;
+ unsigned int port_seq;
+ unsigned int cpu_type;
+ unsigned long irq_cec;
void __iomem *exit_reg;
void __iomem *cec_reg;
void __iomem *hdmi_rxreg;
void __iomem *hhi_reg;
-
- /* kernel resource */
- struct input_dev *remote_cec_dev;
- struct notifier_block hdmitx_nb;
+ struct hdmitx_dev *tx_dev;
struct workqueue_struct *cec_thread;
struct device *dbg_dev;
+ const char *pin_name;
struct delayed_work cec_work;
struct completion rx_ok;
struct completion tx_ok;
spinlock_t cec_reg_lock;
struct mutex cec_mutex;
- struct hrtimer start_bit_check;
+ struct mutex cec_ioctl_mutex;
+#ifdef CONFIG_PM
+ int cec_suspend;
+#endif
+ struct vendor_info_data v_data;
+ struct cec_global_info_t cec_info;
+ struct cec_platform_data_s *plat_data;
+};
+
+struct cec_msg_last {
+ unsigned char msg[MAX_MSG];
+ int len;
+ int last_result;
+ unsigned long last_jiffies;
+};
+static struct cec_msg_last *last_cec_msg;
+
+static int phy_addr_test;
+
+/* from android cec hal */
+enum {
+ HDMI_OPTION_WAKEUP = 1,
+ HDMI_OPTION_ENABLE_CEC = 2,
+ HDMI_OPTION_SYSTEM_CEC_CONTROL = 3,
+ HDMI_OPTION_SET_LANG = 5,
+ HDMI_OPTION_SERVICE_FLAG = 16,
};
static struct ao_cec_dev *cec_dev;
+static int cec_tx_result;
+
+static int cec_line_cnt;
+static struct hrtimer start_bit_check;
+
+static unsigned char rx_msg[MAX_MSG];
+static unsigned char rx_len;
+static unsigned int new_msg;
+static bool wake_ok = 1;
+static bool ee_cec;
+static bool pin_status;
+static bool cec_msg_dbg_en;
#define CEC_ERR(format, args...) \
{if (cec_dev->dbg_dev) \
@@ -152,17 +162,18 @@ static struct ao_cec_dev *cec_dev;
}
#define CEC_INFO(format, args...) \
- {if (cec_dev->cec_msg_dbg_en && cec_dev->dbg_dev) \
+ {if (cec_msg_dbg_en && cec_dev->dbg_dev) \
dev_info(cec_dev->dbg_dev, format, ##args); \
}
+static unsigned char msg_log_buf[128] = { 0 };
-#define waiting_aocec_free() \
+#define waiting_aocec_free(r) \
do {\
unsigned long cnt = 0;\
- while (readl(cec_dev->cec_reg + AO_CEC_RW_REG) & (1<<23)) {\
- if (cnt++ >= 3500) { \
- pr_info("waiting aocec free time out.\n");\
+ while (readl(cec_dev->cec_reg + r) & (1<<23)) {\
+ if (cnt++ == 3500) { \
+ pr_info("waiting aocec %x free time out\n", r);\
break;\
} \
} \
@@ -179,12 +190,12 @@ static void cec_set_reg_bits(unsigned int addr, unsigned int value,
writel(data32, cec_dev->cec_reg + addr);
}
-static unsigned int aocec_rd_reg(unsigned long addr)
+unsigned int aocec_rd_reg(unsigned long addr)
{
unsigned int data32;
unsigned long flags;
- waiting_aocec_free();
+ waiting_aocec_free(AO_CEC_RW_REG);
spin_lock_irqsave(&cec_dev->cec_reg_lock, flags);
data32 = 0;
data32 |= 0 << 16; /* [16] cec_reg_wr */
@@ -192,18 +203,18 @@ static unsigned int aocec_rd_reg(unsigned long addr)
data32 |= addr << 0; /* [7:0] cec_reg_addr */
writel(data32, cec_dev->cec_reg + AO_CEC_RW_REG);
- waiting_aocec_free();
+ waiting_aocec_free(AO_CEC_RW_REG);
data32 = ((readl(cec_dev->cec_reg + AO_CEC_RW_REG)) >> 24) & 0xff;
spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags);
return data32;
} /* aocec_rd_reg */
-static void aocec_wr_reg(unsigned long addr, unsigned long data)
+void aocec_wr_reg(unsigned long addr, unsigned long data)
{
unsigned long data32;
unsigned long flags;
- waiting_aocec_free();
+ waiting_aocec_free(AO_CEC_RW_REG);
spin_lock_irqsave(&cec_dev->cec_reg_lock, flags);
data32 = 0;
data32 |= 1 << 16; /* [16] cec_reg_wr */
@@ -213,6 +224,38 @@ static void aocec_wr_reg(unsigned long addr, unsigned long data)
spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags);
} /* aocec_wr_only_reg */
+/*------------for AO_CECB------------------*/
+static unsigned int aocecb_rd_reg(unsigned long addr)
+{
+ unsigned int data32;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cec_dev->cec_reg_lock, flags);
+ data32 = 0;
+ data32 |= 0 << 16; /* [16] cec_reg_wr */
+ data32 |= 0 << 8; /* [15:8] cec_reg_wrdata */
+ data32 |= addr << 0; /* [7:0] cec_reg_addr */
+ writel(data32, cec_dev->cec_reg + AO_CECB_RW_REG);
+
+ data32 = ((readl(cec_dev->cec_reg + AO_CECB_RW_REG)) >> 24) & 0xff;
+ spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags);
+ return data32;
+} /* aocecb_rd_reg */
+
+static void aocecb_wr_reg(unsigned long addr, unsigned long data)
+{
+ unsigned long data32;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cec_dev->cec_reg_lock, flags);
+ data32 = 0;
+ data32 |= 1 << 16; /* [16] cec_reg_wr */
+ data32 |= data << 8; /* [15:8] cec_reg_wrdata */
+ data32 |= addr << 0; /* [7:0] cec_reg_addr */
+ writel(data32, cec_dev->cec_reg + AO_CECB_RW_REG);
+ spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags);
+} /* aocecb_wr_only_reg */
+
/*----------------- low level for EE cec rx/tx support ----------------*/
static inline void hdmirx_set_bits_top(uint32_t reg, uint32_t bits,
uint32_t start, uint32_t len)
@@ -225,21 +268,47 @@ static inline void hdmirx_set_bits_top(uint32_t reg, uint32_t bits,
hdmirx_wr_top(reg, tmp);
}
+static unsigned int hdmirx_cec_read(unsigned int reg)
+{
+ /*
+ * TXLX has moved ee cec to ao domain
+ */
+ if (reg >= DWC_CEC_CTRL && cec_dev->plat_data->ee_to_ao)
+ return aocecb_rd_reg((reg - DWC_CEC_CTRL) / 4);
+ else
+ return hdmirx_rd_dwc(reg);
+}
+
+/*only for ee cec*/
+static void hdmirx_cec_write(unsigned int reg, unsigned int value)
+{
+ /*
+ * TXLX has moved ee cec to ao domain
+ */
+ if (reg >= DWC_CEC_CTRL && cec_dev->plat_data->ee_to_ao)
+ aocecb_wr_reg((reg - DWC_CEC_CTRL) / 4, value);
+ else
+ hdmirx_wr_dwc(reg, value);
+}
+
static inline void hdmirx_set_bits_dwc(uint32_t reg, uint32_t bits,
uint32_t start, uint32_t len)
{
unsigned int tmp;
- tmp = hdmirx_rd_dwc(reg);
+ tmp = hdmirx_cec_read(reg);
tmp &= ~(((1 << len) - 1) << start);
tmp |= (bits << start);
- hdmirx_wr_dwc(reg, tmp);
+ hdmirx_cec_write(reg, tmp);
}
-static void cecrx_hw_reset(void)
+void cecrx_hw_reset(void)
{
/* cec disable */
- hdmirx_set_bits_dwc(DWC_DMI_DISABLE_IF, 0, 5, 1);
+ if (!cec_dev->plat_data->ee_to_ao)
+ hdmirx_set_bits_dwc(DWC_DMI_DISABLE_IF, 0, 5, 1);
+ else
+ cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1);
udelay(500);
}
@@ -247,37 +316,33 @@ static void cecrx_check_irq_enable(void)
{
unsigned int reg32;
- reg32 = hdmirx_rd_dwc(DWC_AUD_CLK_IEN);
+ /* irq on chip txlx has sperate from EE cec, no need check */
+ if (cec_dev->plat_data->ee_to_ao)
+ return;
+
+ reg32 = hdmirx_cec_read(DWC_AUD_CEC_IEN);
if ((reg32 & EE_CEC_IRQ_EN_MASK) != EE_CEC_IRQ_EN_MASK) {
CEC_INFO("irq_en is wrong:%x, checker:%pf\n",
reg32, (void *)_RET_IP_);
- hdmirx_wr_dwc(DWC_AUD_CLK_IEN_SET, EE_CEC_IRQ_EN_MASK);
+ hdmirx_cec_write(DWC_AUD_CEC_IEN_SET, EE_CEC_IRQ_EN_MASK);
}
}
-static void format_msg_str(const char *msg, char len, char *prefix, char *buf)
-{
- int size = 0, i;
-
- size = sprintf(buf + size, "%s %2d:", prefix, len);
- for (i = 0; i < len; i++)
- size += sprintf(buf + size, " %02x", msg[i]);
- buf[size] = '\0';
- WARN_ON(size >= DBG_BUF_SIZE);
-}
-
static int cecrx_trigle_tx(const unsigned char *msg, unsigned char len)
{
- int i = 0;
+ int i = 0, size = 0;
int lock;
cecrx_check_irq_enable();
while (1) {
/* send is in process */
- lock = hdmirx_rd_dwc(DWC_CEC_LOCK);
- if (lock)
+ lock = hdmirx_cec_read(DWC_CEC_LOCK);
+ if (lock) {
CEC_ERR("recevie msg in tx\n");
- if (hdmirx_rd_dwc(DWC_CEC_CTRL) & 0x01)
+ cecrx_irq_handle();
+ return -1;
+ }
+ if (hdmirx_cec_read(DWC_CEC_CTRL) & 0x01)
i++;
else
break;
@@ -287,73 +352,97 @@ static int cecrx_trigle_tx(const unsigned char *msg, unsigned char len)
}
msleep(20);
}
-
- for (i = 0; i < len; i++)
- hdmirx_wr_dwc(DWC_CEC_TX_DATA0 + i * 4, msg[i]);
-
- if (cec_dev->cec_msg_dbg_en) {
- char buf[DBG_BUF_SIZE] = {};
-
- format_msg_str(msg, len, "CEC tx msg", buf);
- pr_info("%s\n", buf);
+ size += sprintf(msg_log_buf + size, "CEC tx msg len %d:", len);
+ for (i = 0; i < len; i++) {
+ hdmirx_cec_write(DWC_CEC_TX_DATA0 + i * 4, msg[i]);
+ size += sprintf(msg_log_buf + size, " %02x", msg[i]);
}
-
+ msg_log_buf[size] = '\0';
+ CEC_INFO("%s\n", msg_log_buf);
/* start send */
- hdmirx_wr_dwc(DWC_CEC_TX_CNT, len);
+ hdmirx_cec_write(DWC_CEC_TX_CNT, len);
hdmirx_set_bits_dwc(DWC_CEC_CTRL, 3, 0, 3);
return 0;
}
-static int cec_pick_msg(unsigned char *msg)
+int cec_has_irq(void)
{
- int i;
+ unsigned int intr_cec;
+
+ if (!cec_dev->plat_data->ee_to_ao) {
+ intr_cec = hdmirx_cec_read(DWC_AUD_CEC_ISTS);
+ intr_cec &= EE_CEC_IRQ_EN_MASK;
+ } else {
+ intr_cec = readl(cec_dev->cec_reg + AO_CECB_INTR_STAT);
+ intr_cec &= CECB_IRQ_EN_MASK;
+ }
+ return intr_cec;
+}
+
+static inline void cecrx_clear_irq(unsigned int flags)
+{
+ if (!cec_dev->plat_data->ee_to_ao)
+ hdmirx_cec_write(DWC_AUD_CEC_ICLR, flags);
+ else
+ writel(flags, cec_dev->cec_reg + AO_CECB_INTR_CLR);
+}
+
+static int cec_pick_msg(unsigned char *msg, unsigned char *out_len)
+{
+ int i, size;
int len;
struct delayed_work *dwork;
dwork = &cec_dev->cec_work;
- len = hdmirx_rd_dwc(DWC_CEC_RX_CNT);
- for (i = 0; i < len; i++)
- msg[i] = hdmirx_rd_dwc(DWC_CEC_RX_DATA0 + i * 4);
+ len = hdmirx_cec_read(DWC_CEC_RX_CNT);
+ size = sprintf(msg_log_buf, "CEC RX len %d:", len);
+ for (i = 0; i < len; i++) {
+ msg[i] = hdmirx_cec_read(DWC_CEC_RX_DATA0 + i * 4);
+ size += sprintf(msg_log_buf + size, " %02x", msg[i]);
+ }
+ size += sprintf(msg_log_buf + size, "\n");
+ msg_log_buf[size] = '\0';
/* clr CEC lock bit */
- hdmirx_wr_dwc(DWC_CEC_LOCK, 0);
+ hdmirx_cec_write(DWC_CEC_LOCK, 0);
mod_delayed_work(cec_dev->cec_thread, dwork, 0);
- if (cec_dev->cec_msg_dbg_en) {
- char buf[DBG_BUF_SIZE] = {};
-
- format_msg_str(msg, len, "CEC rx msg", buf);
- pr_info("%s\n", buf);
- }
- cec_dev->rx_len = len;
- cec_dev->pin_status = 1;
+ CEC_INFO("%s", msg_log_buf);
+ if (((msg[0] & 0xf0) >> 4) == cec_dev->cec_info.log_addr) {
+ *out_len = 0;
+ CEC_ERR("bad iniator with self:%s", msg_log_buf);
+ } else
+ *out_len = len;
+ pin_status = 1;
return 0;
}
-static void cecrx_irq_handle(void)
+void cecrx_irq_handle(void)
{
uint32_t intr_cec;
uint32_t lock;
+ int shift = 0;
- intr_cec = (hdmirx_rd_dwc(DWC_AUD_CLK_ISTS) & EE_CEC_IRQ_EN_MASK);
+ intr_cec = cec_has_irq();
/* clear irq */
if (intr_cec != 0)
- hdmirx_wr_dwc(DWC_AUD_CLK_ICLR, intr_cec);
+ cecrx_clear_irq(intr_cec);
- if (!cec_dev->ee_cec)
+ if (!ee_cec)
return;
+ if (cec_dev->plat_data->ee_to_ao)
+ shift = 16;
/* TX DONE irq, increase tx buffer pointer */
if (intr_cec & CEC_IRQ_TX_DONE) {
- cec_dev->cec_tx_result = CEC_FAIL_NONE;
+ cec_tx_result = CEC_FAIL_NONE;
complete(&cec_dev->tx_ok);
}
- lock = hdmirx_rd_dwc(DWC_CEC_LOCK);
+ lock = hdmirx_cec_read(DWC_CEC_LOCK);
/* EOM irq, message is coming */
if ((intr_cec & CEC_IRQ_RX_EOM) || lock) {
- cec_pick_msg(cec_dev->rx_msg);
+ cec_pick_msg(rx_msg, &rx_len);
complete(&cec_dev->rx_ok);
- cec_dev->new_msg = 1;
}
/* TX error irq flags */
@@ -363,14 +452,14 @@ static void cecrx_irq_handle(void)
if (!(intr_cec & CEC_IRQ_TX_NACK))
CEC_ERR("tx msg failed, flag:%08x\n", intr_cec);
if (intr_cec & CEC_IRQ_TX_NACK)
- cec_dev->cec_tx_result = CEC_FAIL_NACK;
+ cec_tx_result = CEC_FAIL_NACK;
else if (intr_cec & CEC_IRQ_TX_ARB_LOST) {
- cec_dev->cec_tx_result = CEC_FAIL_BUSY;
+ cec_tx_result = CEC_FAIL_BUSY;
/* clear start */
- hdmirx_wr_dwc(DWC_CEC_TX_CNT, 0);
+ hdmirx_cec_write(DWC_CEC_TX_CNT, 0);
hdmirx_set_bits_dwc(DWC_CEC_CTRL, 0, 0, 3);
} else
- cec_dev->cec_tx_result = CEC_FAIL_OTHER;
+ cec_tx_result = CEC_FAIL_OTHER;
complete(&cec_dev->tx_ok);
}
@@ -382,7 +471,7 @@ static void cecrx_irq_handle(void)
if (intr_cec & CEC_IRQ_RX_WAKEUP) {
CEC_INFO("rx wake up\n");
- hdmirx_wr_dwc(DWC_CEC_WKUPCTRL, 0);
+ hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0);
/* TODO: wake up system if needed */
}
}
@@ -393,73 +482,134 @@ static irqreturn_t cecrx_isr(int irq, void *dev_instance)
return IRQ_HANDLED;
}
-static void cec_hw_buf_clear(void)
+static void ao_cecb_init(void)
{
- aocec_wr_reg(CEC_RX_MSG_CMD, RX_DISABLE);
- aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT);
- aocec_wr_reg(CEC_RX_CLEAR_BUF, 1);
- aocec_wr_reg(CEC_TX_CLEAR_BUF, 1);
- udelay(100);
- aocec_wr_reg(CEC_RX_CLEAR_BUF, 0);
- aocec_wr_reg(CEC_TX_CLEAR_BUF, 0);
- udelay(100);
- aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP);
- aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+ unsigned long data32;
+ unsigned int reg;
+
+ if (!cec_dev->plat_data->ee_to_ao)
+ return;
+
+ reg = (0 << 31) |
+ (0 << 30) |
+ (1 << 28) | /* clk_div0/clk_div1 in turn */
+ ((732-1) << 12) | /* Div_tcnt1 */
+ ((733-1) << 0); /* Div_tcnt0 */
+ writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0);
+ reg = (0 << 13) |
+ ((11-1) << 12) |
+ ((8-1) << 0);
+ writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1);
+
+ reg = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0);
+ reg |= (1 << 31);
+ writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0);
+
+ udelay(200);
+ reg |= (1 << 30);
+ writel(reg, cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0);
+
+ reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0);
+ reg |= (0x01 << 14); /* xtal gate */
+ writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0);
+
+ data32 = 0;
+ data32 |= (7 << 12); /* filter_del */
+ data32 |= (1 << 8); /* filter_tick: 1us */
+ data32 |= (1 << 3); /* enable system clock */
+ data32 |= 0 << 1; /* [2:1] cntl_clk: */
+ /* 0=Disable clk (Power-off mode); */
+ /* 1=Enable gated clock (Normal mode); */
+ /* 2=Enable free-run clk (Debug mode). */
+ data32 |= 1 << 0; /* [0] sw_reset: 1=Reset */
+ writel(data32, cec_dev->cec_reg + AO_CECB_GEN_CNTL);
+ /* Enable gated clock (Normal mode). */
+ cec_set_reg_bits(AO_CECB_GEN_CNTL, 1, 1, 1);
+ /* Release SW reset */
+ cec_set_reg_bits(AO_CECB_GEN_CNTL, 0, 0, 1);
+
+ /* Enable all AO_CECB interrupt sources */
+ cec_irq_enable(true);
+ hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0);
}
-static void cec_logicaddr_set(int l_add)
+void eecec_irq_enable(bool enable)
{
- /* save logical address for suspend/wake up */
- cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4);
- if (cec_dev->ee_cec) {
- /* set ee_cec logical addr */
- if (l_add < 8)
- hdmirx_wr_dwc(DWC_CEC_ADDR_L, 1 << l_add);
+ if (cec_dev->cpu_type < MESON_CPU_MAJOR_ID_TXLX) {
+ if (enable)
+ hdmirx_cec_write(DWC_AUD_CEC_IEN_SET,
+ EE_CEC_IRQ_EN_MASK);
+ else {
+ hdmirx_cec_write(DWC_AUD_CEC_ICLR,
+ (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) |
+ EE_CEC_IRQ_EN_MASK));
+ hdmirx_cec_write(DWC_AUD_CEC_IEN_SET,
+ hdmirx_cec_read(DWC_AUD_CEC_IEN) &
+ ~EE_CEC_IRQ_EN_MASK);
+ hdmirx_cec_write(DWC_AUD_CEC_IEN_CLR,
+ (~(hdmirx_cec_read(DWC_AUD_CEC_IEN)) |
+ EE_CEC_IRQ_EN_MASK));
+ }
+ CEC_INFO("ee enable:int mask:0x%x\n",
+ hdmirx_cec_read(DWC_AUD_CEC_IEN));
+ } else {
+ if (enable)
+ writel(CECB_IRQ_EN_MASK,
+ cec_dev->cec_reg + AO_CECB_INTR_MASKN);
else
- hdmirx_wr_dwc(DWC_CEC_ADDR_H, 1 << (l_add - 8) | 0x80);
- return;
+ writel(readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN)
+ & ~CECB_IRQ_EN_MASK,
+ cec_dev->cec_reg + AO_CECB_INTR_MASKN);
+ CEC_INFO("ao move enable:int mask:0x%x\n",
+ readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN));
}
- aocec_wr_reg(CEC_LOGICAL_ADDR0, 0);
- cec_hw_buf_clear();
- aocec_wr_reg(CEC_LOGICAL_ADDR0, (l_add & 0xf));
- udelay(100);
- aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | (l_add & 0xf));
- if (cec_dev->cec_msg_dbg_en)
- CEC_INFO("set logical addr:0x%x\n",
- aocec_rd_reg(CEC_LOGICAL_ADDR0));
}
-static int cecrx_hw_init(void)
+void cec_irq_enable(bool enable)
+{
+ if (ee_cec)
+ eecec_irq_enable(enable);
+ else
+ aocec_irq_enable(enable);
+}
+
+int cecrx_hw_init(void)
{
unsigned int data32;
- if (!cec_dev->ee_cec)
+ if (!ee_cec)
return -1;
cecrx_hw_reset();
- /* set cec clk 32768k */
- data32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL);
- data32 = 0;
- /* [17:16] clk_sel: 0=oscin; 1=slow_oscin; 2=fclk_div3; 3=fclk_div5. */
- data32 |= 0 << 16;
- /* [ 15] clk_en */
- data32 |= 1 << 15;
- /* [13: 0] clk_div */
- data32 |= (732-1) << 0;
- writel(data32, cec_dev->hhi_reg + HHI_32K_CLK_CNTL);
- hdmirx_wr_top(TOP_EDID_ADDR_CEC, EDID_CEC_ID_ADDR);
-
- /* hdmirx_cecclk_en */
- hdmirx_set_bits_top(TOP_CLK_CNTL, 1, 2, 1);
- hdmirx_set_bits_top(TOP_EDID_GEN_CNTL, EDID_AUTO_CEC_EN, 11, 1);
-
- /* enable all cec irq */
- hdmirx_wr_dwc(DWC_AUD_CLK_IEN_SET, EE_CEC_IRQ_EN_MASK);
- /* clear all wake up source */
- hdmirx_wr_dwc(DWC_CEC_WKUPCTRL, 0);
- /* cec enable */
- hdmirx_set_bits_dwc(DWC_DMI_DISABLE_IF, 1, 5, 1);
-
- cec_logicaddr_set(cec_dev->my_log_addr);
+ if (!cec_dev->plat_data->ee_to_ao) {
+ /* set cec clk 32768k */
+ data32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL);
+ data32 = 0;
+ /*
+ * [17:16] clk_sel: 0=oscin; 1=slow_oscin;
+ * 2=fclk_div3; 3=fclk_div5.
+ */
+ data32 |= 0 << 16;
+ /* [ 15] clk_en */
+ data32 |= 1 << 15;
+ /* [13: 0] clk_div */
+ data32 |= (732-1) << 0;
+ writel(data32, cec_dev->hhi_reg + HHI_32K_CLK_CNTL);
+ hdmirx_wr_top(TOP_EDID_ADDR_CEC, EDID_CEC_ID_ADDR);
+
+ /* hdmirx_cecclk_en */
+ hdmirx_set_bits_top(TOP_CLK_CNTL, 1, 2, 1);
+ hdmirx_set_bits_top(TOP_EDID_GEN_CNTL, EDID_AUTO_CEC_EN, 11, 1);
+
+ /* enable all cec irq */
+ cec_irq_enable(true);
+ /* clear all wake up source */
+ hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0);
+ /* cec enable */
+ hdmirx_set_bits_dwc(DWC_DMI_DISABLE_IF, 1, 5, 1);
+ } else
+ ao_cecb_init();
+
+ cec_logicaddr_set(cec_dev->cec_info.log_addr);
return 0;
}
@@ -469,41 +619,56 @@ static int dump_cecrx_reg(char *b)
unsigned char reg;
unsigned int reg32;
- reg32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL);
- s += sprintf(b + s, "HHI_32K_CLK_CNTL: 0x%08x\n", reg32);
- reg32 = hdmirx_rd_top(TOP_EDID_ADDR_CEC);
- s += sprintf(b + s, "TOP_EDID_ADDR_CEC: 0x%08x\n", reg32);
- reg32 = hdmirx_rd_top(TOP_EDID_GEN_CNTL);
- s += sprintf(b + s, "TOP_EDID_GEN_CNTL: 0x%08x\n", reg32);
- reg32 = hdmirx_rd_dwc(DWC_AUD_CLK_IEN);
- s += sprintf(b + s, "DWC_AUD_CLK_IEN: 0x%08x\n", reg32);
- reg32 = hdmirx_rd_dwc(DWC_AUD_CLK_ISTS);
- s += sprintf(b + s, "DWC_AUD_CLK_ISTS: 0x%08x\n", reg32);
- reg32 = hdmirx_rd_dwc(DWC_DMI_DISABLE_IF);
- s += sprintf(b + s, "DWC_DMI_DISABLE_IF: 0x%08x\n", reg32);
- reg32 = hdmirx_rd_top(TOP_CLK_CNTL);
- s += sprintf(b + s, "TOP_CLK_CNTL: 0x%08x\n", reg32);
+ if (!cec_dev->plat_data->ee_to_ao) {
+ reg32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL);
+ s += sprintf(b + s, "HHI_32K_CLK_CNTL: 0x%08x\n", reg32);
+ reg32 = hdmirx_rd_top(TOP_EDID_ADDR_CEC);
+ s += sprintf(b + s, "TOP_EDID_ADDR_CEC: 0x%08x\n", reg32);
+ reg32 = hdmirx_rd_top(TOP_EDID_GEN_CNTL);
+ s += sprintf(b + s, "TOP_EDID_GEN_CNTL: 0x%08x\n", reg32);
+ reg32 = hdmirx_cec_read(DWC_AUD_CEC_IEN);
+ s += sprintf(b + s, "DWC_AUD_CEC_IEN: 0x%08x\n", reg32);
+ reg32 = hdmirx_cec_read(DWC_AUD_CEC_ISTS);
+ s += sprintf(b + s, "DWC_AUD_CEC_ISTS: 0x%08x\n", reg32);
+ reg32 = hdmirx_cec_read(DWC_DMI_DISABLE_IF);
+ s += sprintf(b + s, "DWC_DMI_DISABLE_IF: 0x%08x\n", reg32);
+ reg32 = hdmirx_rd_top(TOP_CLK_CNTL);
+ s += sprintf(b + s, "TOP_CLK_CNTL: 0x%08x\n", reg32);
+ } else {
+ reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0);
+ s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG0: 0x%08x\n", reg32);
+ reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1);
+ s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG1: 0x%08x\n", reg32);
+ reg32 = readl(cec_dev->cec_reg + AO_CECB_GEN_CNTL);
+ s += sprintf(b + s, "AO_CECB_GEN_CNTL: 0x%08x\n", reg32);
+ reg32 = readl(cec_dev->cec_reg + AO_CECB_RW_REG);
+ s += sprintf(b + s, "AO_CECB_RW_REG: 0x%08x\n", reg32);
+ reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN);
+ s += sprintf(b + s, "AO_CECB_INTR_MASKN: 0x%08x\n", reg32);
+ reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_STAT);
+ s += sprintf(b + s, "AO_CECB_INTR_STAT: 0x%08x\n", reg32);
+ }
s += sprintf(b + s, "CEC MODULE REGS:\n");
- s += sprintf(b + s, "CEC_CTRL = 0x%02x\n", hdmirx_rd_dwc(0x1f00));
- s += sprintf(b + s, "CEC_MASK = 0x%02x\n", hdmirx_rd_dwc(0x1f08));
- s += sprintf(b + s, "CEC_ADDR_L = 0x%02x\n", hdmirx_rd_dwc(0x1f14));
- s += sprintf(b + s, "CEC_ADDR_H = 0x%02x\n", hdmirx_rd_dwc(0x1f18));
- s += sprintf(b + s, "CEC_TX_CNT = 0x%02x\n", hdmirx_rd_dwc(0x1f1c));
- s += sprintf(b + s, "CEC_RX_CNT = 0x%02x\n", hdmirx_rd_dwc(0x1f20));
- s += sprintf(b + s, "CEC_LOCK = 0x%02x\n", hdmirx_rd_dwc(0x1fc0));
- s += sprintf(b + s, "CEC_WKUPCTRL = 0x%02x\n", hdmirx_rd_dwc(0x1fc4));
+ s += sprintf(b + s, "CEC_CTRL = 0x%02x\n", hdmirx_cec_read(0x1f00));
+ s += sprintf(b + s, "CEC_MASK = 0x%02x\n", hdmirx_cec_read(0x1f08));
+ s += sprintf(b + s, "CEC_ADDR_L = 0x%02x\n", hdmirx_cec_read(0x1f14));
+ s += sprintf(b + s, "CEC_ADDR_H = 0x%02x\n", hdmirx_cec_read(0x1f18));
+ s += sprintf(b + s, "CEC_TX_CNT = 0x%02x\n", hdmirx_cec_read(0x1f1c));
+ s += sprintf(b + s, "CEC_RX_CNT = 0x%02x\n", hdmirx_cec_read(0x1f20));
+ s += sprintf(b + s, "CEC_LOCK = 0x%02x\n", hdmirx_cec_read(0x1fc0));
+ s += sprintf(b + s, "CEC_WKUPCTRL = 0x%02x\n", hdmirx_cec_read(0x1fc4));
s += sprintf(b + s, "%s", "RX buffer:");
for (i = 0; i < 16; i++) {
- reg = (hdmirx_rd_dwc(0x1f80 + i * 4) & 0xff);
+ reg = (hdmirx_cec_read(0x1f80 + i * 4) & 0xff);
s += sprintf(b + s, " %02x", reg);
}
s += sprintf(b + s, "\n");
s += sprintf(b + s, "%s", "TX buffer:");
for (i = 0; i < 16; i++) {
- reg = (hdmirx_rd_dwc(0x1f40 + i * 4) & 0xff);
+ reg = (hdmirx_cec_read(0x1f40 + i * 4) & 0xff);
s += sprintf(b + s, " %02x", reg);
}
s += sprintf(b + s, "\n");
@@ -512,75 +677,55 @@ static int dump_cecrx_reg(char *b)
/*--------------------- END of EE CEC --------------------*/
-static void cec_enable_irq(void)
+void aocec_irq_enable(bool enable)
{
- cec_set_reg_bits(AO_CEC_INTR_MASKN, 0x6, 0, 3);
- CEC_INFO("enable:int mask:0x%x\n",
+ if (enable)
+ cec_set_reg_bits(AO_CEC_INTR_MASKN, 0x6, 0, 3);
+ else
+ cec_set_reg_bits(AO_CEC_INTR_MASKN, 0x0, 0, 3);
+ CEC_INFO("ao enable:int mask:0x%x\n",
readl(cec_dev->cec_reg + AO_CEC_INTR_MASKN));
}
-static void cec_arbit_bit_time_set(unsigned int bit_set,
- unsigned int time_set, unsigned int flag)
-{ /* 11bit:bit[10:0] */
- if (flag) {
- CEC_INFO("bit_set:0x%x;time_set:0x%x\n",
- bit_set, time_set);
- }
+static void cec_hw_buf_clear(void)
+{
+ aocec_wr_reg(CEC_RX_MSG_CMD, RX_DISABLE);
+ aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT);
+ aocec_wr_reg(CEC_RX_CLEAR_BUF, 1);
+ aocec_wr_reg(CEC_TX_CLEAR_BUF, 1);
+ udelay(100);
+ aocec_wr_reg(CEC_RX_CLEAR_BUF, 0);
+ aocec_wr_reg(CEC_TX_CLEAR_BUF, 0);
+ udelay(100);
+ aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP);
+ aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+}
- switch (bit_set) {
- case 3:
- /* 3 bit */
- if (flag) {
- CEC_INFO("read 3 bit:0x%x%x\n",
- aocec_rd_reg(AO_CEC_TXTIME_4BIT_BIT10_8),
- aocec_rd_reg(AO_CEC_TXTIME_4BIT_BIT7_0));
- }
- aocec_wr_reg(AO_CEC_TXTIME_4BIT_BIT7_0, time_set & 0xff);
- aocec_wr_reg(AO_CEC_TXTIME_4BIT_BIT10_8, (time_set >> 8) & 0x7);
- if (flag) {
- CEC_INFO("write 3 bit:0x%x%x\n",
- aocec_rd_reg(AO_CEC_TXTIME_4BIT_BIT10_8),
- aocec_rd_reg(AO_CEC_TXTIME_4BIT_BIT7_0));
- }
- break;
- /* 5 bit */
- case 5:
- if (flag) {
- CEC_INFO("read 5 bit:0x%x%x\n",
- aocec_rd_reg(AO_CEC_TXTIME_2BIT_BIT10_8),
- aocec_rd_reg(AO_CEC_TXTIME_2BIT_BIT7_0));
- }
- aocec_wr_reg(AO_CEC_TXTIME_2BIT_BIT7_0, time_set & 0xff);
- aocec_wr_reg(AO_CEC_TXTIME_2BIT_BIT10_8, (time_set >> 8) & 0x7);
- if (flag) {
- CEC_INFO("write 5 bit:0x%x%x\n",
- aocec_rd_reg(AO_CEC_TXTIME_2BIT_BIT10_8),
- aocec_rd_reg(AO_CEC_TXTIME_2BIT_BIT7_0));
- }
- break;
- /* 7 bit */
- case 7:
- if (flag) {
- CEC_INFO("read 7 bit:0x%x%x\n",
- aocec_rd_reg(AO_CEC_TXTIME_17MS_BIT10_8),
- aocec_rd_reg(AO_CEC_TXTIME_17MS_BIT7_0));
- }
- aocec_wr_reg(AO_CEC_TXTIME_17MS_BIT7_0, time_set & 0xff);
- aocec_wr_reg(AO_CEC_TXTIME_17MS_BIT10_8, (time_set >> 8) & 0x7);
- if (flag) {
- CEC_INFO("write 7 bit:0x%x%x\n",
- aocec_rd_reg(AO_CEC_TXTIME_17MS_BIT10_8),
- aocec_rd_reg(AO_CEC_TXTIME_17MS_BIT7_0));
- }
- break;
- default:
- break;
+void cec_logicaddr_set(int l_add)
+{
+ /* save logical address for suspend/wake up */
+ cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4);
+ if (ee_cec) {
+ /* set ee_cec logical addr */
+ if (l_add < 8)
+ hdmirx_cec_write(DWC_CEC_ADDR_L, 1 << l_add);
+ else
+ hdmirx_cec_write(DWC_CEC_ADDR_H, 1 << (l_add - 8)|0x80);
+ return;
}
+ aocec_wr_reg(CEC_LOGICAL_ADDR0, 0);
+ cec_hw_buf_clear();
+ aocec_wr_reg(CEC_LOGICAL_ADDR0, (l_add & 0xf));
+ udelay(100);
+ aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | (l_add & 0xf));
+ if (cec_msg_dbg_en)
+ CEC_INFO("set logical addr:0x%x\n",
+ aocec_rd_reg(CEC_LOGICAL_ADDR0));
}
static void cec_hw_reset(void)
{
- if (cec_dev->ee_cec) {
+ if (ee_cec) {
cecrx_hw_init();
return;
}
@@ -593,9 +738,9 @@ static void cec_hw_reset(void)
cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1);
/* Enable all AO_CEC interrupt sources */
- cec_set_reg_bits(AO_CEC_INTR_MASKN, 0x6, 0, 3);
+ cec_irq_enable(true);
- cec_logicaddr_set(cec_dev->my_log_addr);
+ cec_logicaddr_set(cec_dev->cec_info.log_addr);
/* Cec arbitration 3/5/7 bit time set. */
cec_arbit_bit_time_set(3, 0x118, 0);
@@ -606,17 +751,66 @@ static void cec_hw_reset(void)
aocec_rd_reg(CEC_LOGICAL_ADDR0));
}
-static void cec_rx_buf_clear(void)
+void cec_rx_buf_clear(void)
{
aocec_wr_reg(CEC_RX_CLEAR_BUF, 0x1);
aocec_wr_reg(CEC_RX_CLEAR_BUF, 0x0);
}
-static int cec_rx_buf_check(void)
+static inline bool is_poll_message(unsigned char header)
+{
+ unsigned char initiator, follower;
+
+ initiator = (header >> 4) & 0xf;
+ follower = (header) & 0xf;
+ return initiator == follower;
+}
+
+static inline bool is_feature_abort_msg(const unsigned char *msg, int len)
+{
+ if (!msg || len < 2)
+ return false;
+ if (msg[1] == CEC_OC_FEATURE_ABORT)
+ return true;
+ return false;
+}
+
+static inline bool is_report_phy_addr_msg(const unsigned char *msg, int len)
+{
+ if (!msg || len < 4)
+ return false;
+ if (msg[1] == CEC_OC_REPORT_PHYSICAL_ADDRESS)
+ return true;
+ return false;
+}
+
+static bool need_nack_repeat_msg(const unsigned char *msg, int len, int t)
+{
+ if (len == last_cec_msg->len &&
+ (is_poll_message(msg[0]) || is_feature_abort_msg(msg, len) ||
+ is_report_phy_addr_msg(msg, len)) &&
+ last_cec_msg->last_result == CEC_FAIL_NACK &&
+ jiffies - last_cec_msg->last_jiffies < t) {
+ return true;
+ }
+ return false;
+}
+
+static void cec_clear_logical_addr(void)
+{
+ if (ee_cec) {
+ hdmirx_cec_write(DWC_CEC_ADDR_L, 0);
+ hdmirx_cec_write(DWC_CEC_ADDR_H, 0x80);
+ } else
+ aocec_wr_reg(CEC_LOGICAL_ADDR0, 0);
+ udelay(100);
+}
+
+int cec_rx_buf_check(void)
{
unsigned int rx_num_msg;
- if (cec_dev->ee_cec) {
+ if (ee_cec) {
cecrx_check_irq_enable();
cecrx_irq_handle();
return 0;
@@ -629,12 +823,12 @@ static int cec_rx_buf_check(void)
return rx_num_msg;
}
-int cec_ll_rx(unsigned char *msg)
+int cec_ll_rx(unsigned char *msg, unsigned char *len)
{
int i;
int ret = -1;
+ int pos;
int rx_stat;
- int len;
rx_stat = aocec_rd_reg(CEC_RX_MSG_STATUS);
if ((rx_stat != RX_DONE) || (aocec_rd_reg(CEC_RX_NUM_MSG) != 1)) {
@@ -646,26 +840,30 @@ int cec_ll_rx(unsigned char *msg)
return ret;
}
- len = aocec_rd_reg(CEC_RX_MSG_LENGTH) + 1;
- cec_dev->rx_len = len;
+ *len = aocec_rd_reg(CEC_RX_MSG_LENGTH) + 1;
- for (i = 0; i < len && i < MAX_MSG; i++)
+ for (i = 0; i < (*len) && i < MAX_MSG; i++)
msg[i] = aocec_rd_reg(CEC_RX_MSG_0_HEADER + i);
ret = rx_stat;
- if (cec_dev->cec_msg_dbg_en) {
- char buf[DBG_BUF_SIZE] = {};
-
- format_msg_str(msg, len, "CEC rx msg", buf);
- pr_info("%s\n", buf);
- }
-
+ /* ignore ping message */
+ if (cec_msg_dbg_en == 1 && *len > 1) {
+ pos = 0;
+ pos += sprintf(msg_log_buf + pos,
+ "CEC: rx msg len: %d dat: ", *len);
+ for (i = 0; i < (*len); i++)
+ pos += sprintf(msg_log_buf + pos, "%02x ", msg[i]);
+ pos += sprintf(msg_log_buf + pos, "\n");
+ msg_log_buf[pos] = '\0';
+ CEC_INFO("%s", msg_log_buf);
+ }
+ last_cec_msg->len = 0; /* invalid back up msg when rx */
writel((1 << 2), cec_dev->cec_reg + AO_CEC_INTR_CLR);
aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT);
aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP);
cec_rx_buf_clear();
- cec_dev->pin_status = 1;
+ pin_status = 1;
return ret;
}
@@ -676,10 +874,12 @@ int cec_ll_rx(unsigned char *msg)
static int cec_ll_trigle_tx(const unsigned char *msg, int len)
{
int i;
+ unsigned int n;
+ int pos;
int reg;
unsigned int j = 40;
unsigned int tx_stat;
- int cec_timeout_cnt = 1;
+ static int cec_timeout_cnt = 1;
while (1) {
tx_stat = aocec_rd_reg(CEC_TX_MSG_STATUS);
@@ -704,48 +904,56 @@ static int cec_ll_trigle_tx(const unsigned char *msg, int len)
aocec_wr_reg(CEC_TX_MSG_LENGTH, len-1);
aocec_wr_reg(CEC_TX_MSG_CMD, TX_REQ_CURRENT);
- if (cec_dev->cec_msg_dbg_en) {
- char buf[DBG_BUF_SIZE] = {};
- format_msg_str(msg, len, "CEC tx msg", buf);
- pr_info("%s\n", buf);
+ if (cec_msg_dbg_en == 1) {
+ pos = 0;
+ pos += sprintf(msg_log_buf + pos,
+ "CEC: tx msg len: %d dat: ", len);
+ for (n = 0; n < len; n++) {
+ pos += sprintf(msg_log_buf + pos,
+ "%02x ", msg[n]);
+ }
+
+ pos += sprintf(msg_log_buf + pos, "\n");
+
+ msg_log_buf[pos] = '\0';
+ pr_info("%s", msg_log_buf);
}
+ cec_timeout_cnt = 0;
return 0;
}
return -1;
}
-static void tx_irq_handle(void)
+void tx_irq_handle(void)
{
unsigned int tx_status = aocec_rd_reg(CEC_TX_MSG_STATUS);
+ cec_tx_result = -1;
switch (tx_status) {
case TX_DONE:
aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
- cec_dev->cec_tx_result = CEC_FAIL_NONE;
+ cec_tx_result = CEC_FAIL_NONE;
break;
case TX_BUSY:
CEC_ERR("TX_BUSY\n");
- cec_dev->cec_tx_result = CEC_FAIL_BUSY;
+ cec_tx_result = CEC_FAIL_BUSY;
break;
case TX_ERROR:
- if (cec_dev->cec_msg_dbg_en == 1)
+ if (cec_msg_dbg_en == 1)
CEC_ERR("TX ERROR!!!\n");
- if (aocec_rd_reg(CEC_RX_MSG_STATUS) == RX_ERROR)
- cec_hw_reset();
- else
- aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP);
- cec_dev->cec_tx_result = CEC_FAIL_NACK;
+ aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT);
+ cec_hw_reset();
+ cec_tx_result = CEC_FAIL_NACK;
break;
case TX_IDLE:
CEC_ERR("TX_IDLE\n");
- cec_dev->cec_tx_result = CEC_FAIL_OTHER;
+ cec_tx_result = CEC_FAIL_OTHER;
break;
default:
- cec_dev->cec_tx_result = CEC_FAIL_OTHER;
break;
}
writel((1 << 1), cec_dev->cec_reg + AO_CEC_INTR_CLR);
@@ -754,35 +962,18 @@ static void tx_irq_handle(void)
static int get_line(void)
{
- int reg, cpu_type, ret = -EINVAL;
+ int reg, ret = -EINVAL;
reg = readl(cec_dev->cec_reg + AO_GPIO_I);
- cpu_type = get_cpu_type();
- switch (cpu_type) {
- case MESON_CPU_MAJOR_ID_GXBB:
- ret = (reg & (1 << 12));
- break;
- case MESON_CPU_MAJOR_ID_GXL:
- case MESON_CPU_MAJOR_ID_GXM:
- ret = (reg & (1 << 8));
- break;
- case MESON_CPU_MAJOR_ID_GXTVBB:
- ret = (reg & (1 << 9));
- break;
- case MESON_CPU_MAJOR_ID_TXL:
- ret = (reg & (1 << 7));
- break;
- default:
- CEC_ERR("unknown cpu type:%d\n", cpu_type);
- break;
- }
+ ret = (reg & (1 << cec_dev->plat_data->line_bit));
+
return ret;
}
static enum hrtimer_restart cec_line_check(struct hrtimer *timer)
{
if (get_line() == 0)
- cec_dev->cec_line_cnt++;
+ cec_line_cnt++;
hrtimer_forward_now(timer, HR_DELAY(1));
return HRTIMER_RESTART;
}
@@ -791,72 +982,33 @@ static int check_confilct(void)
{
int i;
- for (i = 0; i < 50; i++) {
+ for (i = 0; i < 200; i++) {
/*
* sleep 20ms and using hrtimer to check cec line every 1ms
*/
- cec_dev->cec_line_cnt = 0;
- hrtimer_start(&cec_dev->start_bit_check,
- HR_DELAY(1), HRTIMER_MODE_REL);
+ cec_line_cnt = 0;
+ hrtimer_start(&start_bit_check, HR_DELAY(1), HRTIMER_MODE_REL);
msleep(20);
- hrtimer_cancel(&cec_dev->start_bit_check);
- if (cec_dev->cec_line_cnt == 0)
+ hrtimer_cancel(&start_bit_check);
+ if (cec_line_cnt == 0)
break;
- CEC_INFO("line busy:%d\n", cec_dev->cec_line_cnt);
+ CEC_INFO("line busy:%d\n", cec_line_cnt);
}
- if (i >= 50)
+ if (i >= 200)
return -EBUSY;
else
return 0;
}
-static inline bool physical_addr_valid(void)
-{
- if (cec_dev->dev_type == DEV_TYPE_TV)
- return 1;
- if (cec_dev->phy_addr_test)
- return 1;
- if (cec_dev->phy_addr == INVALID_PHY_ADDR)
- return 0;
- return 1;
-}
-
-static int cec_hdmi_tx_notify_handler(struct notifier_block *nb,
- unsigned long value, void *p)
-{
- int ret = 0;
- int phy_addr = 0;
-
- switch (value) {
- case HDMITX_PLUG:
- cec_dev->hpd_state = 1;
- CEC_INFO("%s, HDMITX_PLUG\n", __func__);
- break;
-
- case HDMITX_UNPLUG:
- cec_dev->hpd_state = 0;
- CEC_INFO("%s, HDMITX_UNPLUG\n", __func__);
- break;
-
- case HDMITX_PHY_ADDR_VALID:
- phy_addr = *((int *)p);
- cec_dev->phy_addr = phy_addr & 0xffff;
- cec_dev->hpd_state = 1;
- CEC_INFO("%s, phy_addr %x ok\n", __func__, cec_dev->phy_addr);
- break;
-
- default:
- CEC_INFO("unsupported hdmitx notify:%ld, arg:%p\n", value, p);
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
static bool check_physical_addr_valid(int timeout)
{
while (timeout > 0) {
- if (!physical_addr_valid()) {
+ if (cec_dev->dev_type == DEV_TYPE_TV)
+ break;
+ if (phy_addr_test)
+ break;
+ /* physical address for box */
+ if (cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.valid == 0) {
msleep(100);
timeout--;
} else
@@ -867,21 +1019,37 @@ static bool check_physical_addr_valid(int timeout)
return true;
}
-
/* Return value: < 0: fail, > 0: success */
int cec_ll_tx(const unsigned char *msg, unsigned char len)
{
int ret = -1;
- int t = msecs_to_jiffies(2000);
+ int t = msecs_to_jiffies(ee_cec ? 2000 : 5000);
int retry = 2;
if (len == 0)
return CEC_FAIL_NONE;
+ if (is_poll_message(msg[0]))
+ cec_clear_logical_addr();
+
+ /*
+ * for CEC CTS 9.3. Android will try 3 poll message if got NACK
+ * but AOCEC will retry 4 tx for each poll message. Framework
+ * repeat this poll message so quick makes 12 sequential poll
+ * waveform seen on CEC bus. And did not pass CTS
+ * specification of 9.3
+ */
+ if (!ee_cec && need_nack_repeat_msg(msg, len, t)) {
+ if (!memcmp(msg, last_cec_msg->msg, len)) {
+ CEC_INFO("NACK repeat message:%x\n", len);
+ return CEC_FAIL_NACK;
+ }
+ }
+
mutex_lock(&cec_dev->cec_mutex);
- /* make sure physical address is valid before send */
+ /* make sure we got valid physical address */
if (len >= 2 && msg[1] == CEC_OC_REPORT_PHYSICAL_ADDRESS)
- check_physical_addr_valid(20);
+ check_physical_addr_valid(3);
try_again:
reinit_completion(&cec_dev->tx_ok);
@@ -897,7 +1065,7 @@ try_again:
return CEC_FAIL_BUSY;
}
- if (cec_dev->ee_cec)
+ if (ee_cec)
ret = cecrx_trigle_tx(msg, len);
else
ret = cec_ll_trigle_tx(msg, len);
@@ -912,7 +1080,7 @@ try_again:
mutex_unlock(&cec_dev->cec_mutex);
return CEC_FAIL_BUSY;
}
- cec_dev->cec_tx_result = CEC_FAIL_OTHER;
+ cec_tx_result = -1;
ret = wait_for_completion_timeout(&cec_dev->tx_ok, t);
if (ret <= 0) {
/* timeout or interrupt */
@@ -922,7 +1090,7 @@ try_again:
}
ret = CEC_FAIL_OTHER;
} else {
- ret = cec_dev->cec_tx_result;
+ ret = cec_tx_result;
}
if (ret != CEC_FAIL_NONE && ret != CEC_FAIL_NACK) {
if (retry > 0) {
@@ -933,13 +1101,21 @@ try_again:
}
mutex_unlock(&cec_dev->cec_mutex);
+ if (!ee_cec) {
+ last_cec_msg->last_result = ret;
+ if (ret == CEC_FAIL_NACK) {
+ memcpy(last_cec_msg->msg, msg, len);
+ last_cec_msg->len = len;
+ last_cec_msg->last_jiffies = jiffies;
+ }
+ }
return ret;
}
/* -------------------------------------------------------------------------- */
/* AO CEC0 config */
/* -------------------------------------------------------------------------- */
-static void ao_cec_init(void)
+void ao_cec_init(void)
{
unsigned long data32;
unsigned int reg;
@@ -988,7 +1164,66 @@ static void ao_cec_init(void)
cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1);
/* Enable all AO_CEC interrupt sources */
- cec_enable_irq();
+ cec_irq_enable(true);
+}
+
+void cec_arbit_bit_time_set(unsigned int bit_set,
+ unsigned int time_set, unsigned int flag)
+{ /* 11bit:bit[10:0] */
+ if (flag) {
+ CEC_INFO("bit_set:0x%x;time_set:0x%x\n",
+ bit_set, time_set);
+ }
+
+ switch (bit_set) {
+ case 3:
+ /* 3 bit */
+ if (flag) {
+ CEC_INFO("read 3 bit:0x%x%x\n",
+ aocec_rd_reg(AO_CEC_TXTIME_4BIT_BIT10_8),
+ aocec_rd_reg(AO_CEC_TXTIME_4BIT_BIT7_0));
+ }
+ aocec_wr_reg(AO_CEC_TXTIME_4BIT_BIT7_0, time_set & 0xff);
+ aocec_wr_reg(AO_CEC_TXTIME_4BIT_BIT10_8, (time_set >> 8) & 0x7);
+ if (flag) {
+ CEC_INFO("write 3 bit:0x%x%x\n",
+ aocec_rd_reg(AO_CEC_TXTIME_4BIT_BIT10_8),
+ aocec_rd_reg(AO_CEC_TXTIME_4BIT_BIT7_0));
+ }
+ break;
+ /* 5 bit */
+ case 5:
+ if (flag) {
+ CEC_INFO("read 5 bit:0x%x%x\n",
+ aocec_rd_reg(AO_CEC_TXTIME_2BIT_BIT10_8),
+ aocec_rd_reg(AO_CEC_TXTIME_2BIT_BIT7_0));
+ }
+ aocec_wr_reg(AO_CEC_TXTIME_2BIT_BIT7_0, time_set & 0xff);
+ aocec_wr_reg(AO_CEC_TXTIME_2BIT_BIT10_8, (time_set >> 8) & 0x7);
+ if (flag) {
+ CEC_INFO("write 5 bit:0x%x%x\n",
+ aocec_rd_reg(AO_CEC_TXTIME_2BIT_BIT10_8),
+ aocec_rd_reg(AO_CEC_TXTIME_2BIT_BIT7_0));
+ }
+ break;
+ /* 7 bit */
+ case 7:
+ if (flag) {
+ CEC_INFO("read 7 bit:0x%x%x\n",
+ aocec_rd_reg(AO_CEC_TXTIME_17MS_BIT10_8),
+ aocec_rd_reg(AO_CEC_TXTIME_17MS_BIT7_0));
+ }
+ aocec_wr_reg(AO_CEC_TXTIME_17MS_BIT7_0, time_set & 0xff);
+ aocec_wr_reg(AO_CEC_TXTIME_17MS_BIT10_8, (time_set >> 8) & 0x7);
+ if (flag) {
+ CEC_INFO("write 7 bit:0x%x%x\n",
+ aocec_rd_reg(AO_CEC_TXTIME_17MS_BIT10_8),
+ aocec_rd_reg(AO_CEC_TXTIME_17MS_BIT7_0));
+ }
+ break;
+ default:
+ break;
+ }
}
static unsigned int ao_cec_intr_stat(void)
@@ -996,7 +1231,7 @@ static unsigned int ao_cec_intr_stat(void)
return readl(cec_dev->cec_reg + AO_CEC_INTR_STAT);
}
-static unsigned int cec_intr_stat(void)
+unsigned int cec_intr_stat(void)
{
return ao_cec_intr_stat();
}
@@ -1005,7 +1240,7 @@ static unsigned int cec_intr_stat(void)
*wr_flag: 1 write; value valid
* 0 read; value invalid
*/
-static unsigned int cec_config(unsigned int value, bool wr_flag)
+unsigned int cec_config(unsigned int value, bool wr_flag)
{
if (wr_flag)
cec_set_reg_bits(AO_DEBUG_REG0, value, 0, 8);
@@ -1017,7 +1252,7 @@ static unsigned int cec_config(unsigned int value, bool wr_flag)
*wr_flag:1 write; value valid
* 0 read; value invalid
*/
-static unsigned int cec_phyaddr_config(unsigned int value, bool wr_flag)
+unsigned int cec_phyaddr_config(unsigned int value, bool wr_flag)
{
if (wr_flag)
cec_set_reg_bits(AO_DEBUG_REG1, value, 0, 16);
@@ -1025,9 +1260,9 @@ static unsigned int cec_phyaddr_config(unsigned int value, bool wr_flag)
return readl(cec_dev->cec_reg + AO_DEBUG_REG1);
}
-static void cec_keep_reset(void)
+void cec_keep_reset(void)
{
- if (cec_dev->ee_cec)
+ if (ee_cec)
cecrx_hw_reset();
else
writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL);
@@ -1039,7 +1274,12 @@ static void cec_pre_init(void)
{
unsigned int reg = readl(cec_dev->cec_reg + AO_RTI_STATUS_REG1);
- if (cec_dev->ee_cec) {
+ reg &= 0xfffff;
+ if ((reg & 0xffff) == 0xffff)
+ wake_ok = 0;
+ pr_info("cec: wake up flag:%x\n", reg);
+
+ if (ee_cec) {
cecrx_hw_init();
return;
}
@@ -1048,10 +1288,6 @@ static void cec_pre_init(void)
cec_arbit_bit_time_set(3, 0x118, 0);
cec_arbit_bit_time_set(5, 0x000, 0);
cec_arbit_bit_time_set(7, 0x2aa, 0);
- reg &= 0xfffff;
- if ((reg & 0xffff) == 0xffff)
- cec_dev->wake_ok = 0;
- pr_info("cec: wake up flag:%x\n", reg);
}
static int cec_late_check_rx_buffer(void)
@@ -1065,47 +1301,44 @@ static int cec_late_check_rx_buffer(void)
/*
* start another check if rx buffer is full
*/
- if ((-1) == cec_ll_rx(cec_dev->rx_msg)) {
+ if ((-1) == cec_ll_rx(rx_msg, &rx_len)) {
CEC_INFO("buffer got unrecorgnized msg\n");
cec_rx_buf_clear();
- ret = 0;
- } else {
- mod_delayed_work(cec_dev->cec_thread, dwork, 0);
- ret = 1;
+ return 0;
}
- return ret;
+ mod_delayed_work(cec_dev->cec_thread, dwork, 0);
+ return 1;
}
-static void cec_key_report(int suspend)
+void cec_key_report(int suspend)
{
- input_event(cec_dev->remote_cec_dev, EV_KEY, KEY_POWER, 1);
- input_sync(cec_dev->remote_cec_dev);
- input_event(cec_dev->remote_cec_dev, EV_KEY, KEY_POWER, 0);
- input_sync(cec_dev->remote_cec_dev);
- pm_wakeup_event(cec_dev->dbg_dev, 2000);
+ input_event(cec_dev->cec_info.remote_cec_dev, EV_KEY, KEY_POWER, 1);
+ input_sync(cec_dev->cec_info.remote_cec_dev);
+ input_event(cec_dev->cec_info.remote_cec_dev, EV_KEY, KEY_POWER, 0);
+ input_sync(cec_dev->cec_info.remote_cec_dev);
if (!suspend)
CEC_INFO("== WAKE UP BY CEC ==\n")
else
CEC_INFO("== SLEEP by CEC==\n")
}
-static void cec_give_version(unsigned int dest)
+void cec_give_version(unsigned int dest)
{
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
unsigned char msg[3];
if (dest != 0xf) {
msg[0] = ((index & 0xf) << 4) | dest;
msg[1] = CEC_OC_CEC_VERSION;
- msg[2] = cec_dev->cec_version;
+ msg[2] = cec_dev->cec_info.cec_version;
cec_ll_tx(msg, 3);
}
}
-static void cec_report_physical_address_smp(void)
+void cec_report_physical_address_smp(void)
{
unsigned char msg[5];
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
unsigned char phy_addr_ab, phy_addr_cd;
phy_addr_ab = (cec_dev->phy_addr >> 8) & 0xff;
@@ -1119,13 +1352,13 @@ static void cec_report_physical_address_smp(void)
cec_ll_tx(msg, 5);
}
-static void cec_device_vendor_id(void)
+void cec_device_vendor_id(void)
{
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
unsigned char msg[5];
unsigned int vendor_id;
- vendor_id = cec_dev->vendor_id;
+ vendor_id = cec_dev->v_data.vendor_id;
msg[0] = ((index & 0xf) << 4) | CEC_BROADCAST_ADDR;
msg[1] = CEC_OC_DEVICE_VENDOR_ID;
msg[2] = (vendor_id >> 16) & 0xff;
@@ -1135,9 +1368,9 @@ static void cec_device_vendor_id(void)
cec_ll_tx(msg, 5);
}
-static void cec_give_deck_status(unsigned int dest)
+void cec_give_deck_status(unsigned int dest)
{
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
unsigned char msg[3];
msg[0] = ((index & 0xf) << 4) | dest;
@@ -1146,10 +1379,10 @@ static void cec_give_deck_status(unsigned int dest)
cec_ll_tx(msg, 3);
}
-static void cec_menu_status_smp(int dest, int status)
+void cec_menu_status_smp(int dest, int status)
{
unsigned char msg[3];
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
msg[0] = ((index & 0xf) << 4) | dest;
msg[1] = CEC_OC_MENU_STATUS;
@@ -1160,9 +1393,9 @@ static void cec_menu_status_smp(int dest, int status)
cec_ll_tx(msg, 3);
}
-static void cec_inactive_source(int dest)
+void cec_inactive_source(int dest)
{
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
unsigned char msg[4];
unsigned char phy_addr_ab, phy_addr_cd;
@@ -1176,25 +1409,25 @@ static void cec_inactive_source(int dest)
cec_ll_tx(msg, 4);
}
-static void cec_set_osd_name(int dest)
+void cec_set_osd_name(int dest)
{
- unsigned char index = cec_dev->my_log_addr;
- unsigned char osd_len = strlen(cec_dev->osd_name);
+ unsigned char index = cec_dev->cec_info.log_addr;
+ unsigned char osd_len = strlen(cec_dev->cec_info.osd_name);
unsigned char msg[16];
if (dest != 0xf) {
msg[0] = ((index & 0xf) << 4) | dest;
msg[1] = CEC_OC_SET_OSD_NAME;
- memcpy(&msg[2], cec_dev->osd_name, osd_len);
+ memcpy(&msg[2], cec_dev->cec_info.osd_name, osd_len);
cec_ll_tx(msg, 2 + osd_len);
}
}
-static void cec_active_source_smp(void)
+void cec_active_source_smp(void)
{
unsigned char msg[4];
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
unsigned char phy_addr_ab;
unsigned char phy_addr_cd;
@@ -1207,17 +1440,17 @@ static void cec_active_source_smp(void)
cec_ll_tx(msg, 4);
}
-static void cec_request_active_source(void)
+void cec_request_active_source(void)
{
unsigned char msg[2];
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
msg[0] = ((index & 0xf) << 4) | CEC_BROADCAST_ADDR;
msg[1] = CEC_OC_REQUEST_ACTIVE_SOURCE;
cec_ll_tx(msg, 2);
}
-static void cec_set_stream_path(unsigned char *msg)
+void cec_set_stream_path(unsigned char *msg)
{
unsigned int phy_addr_active;
@@ -1233,9 +1466,9 @@ static void cec_set_stream_path(unsigned char *msg)
}
}
-static void cec_report_power_status(int dest, int status)
+void cec_report_power_status(int dest, int status)
{
- unsigned char index = cec_dev->my_log_addr;
+ unsigned char index = cec_dev->cec_info.log_addr;
unsigned char msg[3];
msg[0] = ((index & 0xf) << 4) | dest;
@@ -1246,31 +1479,31 @@ static void cec_report_power_status(int dest, int status)
static void cec_rx_process(void)
{
- int len = cec_dev->rx_len;
+ int len = rx_len;
int initiator, follower;
int opcode;
unsigned char msg[MAX_MSG] = {};
int dest_phy_addr;
- if (len < 2 || !cec_dev->new_msg) /* ignore ping message */
+ if (len < 2 || !new_msg) /* ignore ping message */
return;
- memcpy(msg, cec_dev->rx_msg, len);
+ memcpy(msg, rx_msg, len);
initiator = ((msg[0] >> 4) & 0xf);
follower = msg[0] & 0xf;
- if (follower != 0xf && follower != cec_dev->my_log_addr) {
+ if (follower != 0xf && follower != cec_dev->cec_info.log_addr) {
CEC_ERR("wrong rx message of bad follower:%x", follower);
return;
}
opcode = msg[1];
switch (opcode) {
case CEC_OC_ACTIVE_SOURCE:
- if (cec_dev->wake_ok == 0) {
+ if (wake_ok == 0) {
int phy_addr = msg[2] << 8 | msg[3];
- if (phy_addr == INVALID_PHY_ADDR)
+ if (phy_addr == 0xffff)
break;
- cec_dev->wake_ok = 1;
+ wake_ok = 1;
phy_addr |= (initiator << 16);
writel(phy_addr, cec_dev->cec_reg + AO_RTI_STATUS_REG1);
CEC_INFO("found wake up source:%x", phy_addr);
@@ -1279,7 +1512,8 @@ static void cec_rx_process(void)
case CEC_OC_ROUTING_CHANGE:
dest_phy_addr = msg[4] << 8 | msg[5];
- if (dest_phy_addr == cec_dev->phy_addr) {
+ if ((dest_phy_addr == cec_dev->phy_addr) &&
+ (cec_dev->cec_suspend == CEC_EARLY_SUSPEND)) {
CEC_INFO("wake up by ROUTING_CHANGE\n");
cec_key_report(0);
}
@@ -1318,13 +1552,17 @@ static void cec_rx_process(void)
break;
case CEC_OC_REQUEST_ACTIVE_SOURCE:
- if (!cec_dev->cec_suspend)
+ if (cec_dev->cec_suspend == CEC_POWER_ON)
cec_active_source_smp();
break;
case CEC_OC_GIVE_DEVICE_POWER_STATUS:
- if (cec_dev->cec_suspend)
+ if (cec_dev->cec_suspend == CEC_DEEP_SUSPEND)
cec_report_power_status(initiator, POWER_STANDBY);
+ else if (cec_dev->cec_suspend == CEC_EARLY_SUSPEND)
+ cec_report_power_status(initiator, TRANS_ON_TO_STANDBY);
+ else if (cec_dev->cec_suspend == CEC_POWER_RESUME)
+ cec_report_power_status(initiator, TRANS_STANDBY_TO_ON);
else
cec_report_power_status(initiator, POWER_ON);
break;
@@ -1338,7 +1576,7 @@ static void cec_rx_process(void)
break;
case CEC_OC_MENU_REQUEST:
- if (cec_dev->cec_suspend)
+ if (cec_dev->cec_suspend != CEC_POWER_ON)
cec_menu_status_smp(initiator, DEVICE_MENU_INACTIVE);
else
cec_menu_status_smp(initiator, DEVICE_MENU_ACTIVE);
@@ -1348,7 +1586,7 @@ static void cec_rx_process(void)
CEC_ERR("unsupported command:%x\n", opcode);
break;
}
- cec_dev->new_msg = 0;
+ new_msg = 0;
}
static bool cec_service_suspended(void)
@@ -1366,7 +1604,7 @@ static void cec_task(struct work_struct *work)
struct delayed_work *dwork;
dwork = &cec_dev->cec_work;
- if (cec_dev && (!cec_dev->wake_ok || cec_service_suspended()))
+ if (cec_dev && (!wake_ok || cec_service_suspended()))
cec_rx_process();
if (!cec_late_check_rx_buffer())
@@ -1384,19 +1622,19 @@ static irqreturn_t cec_isr_handler(int irq, void *dev_instance)
tx_irq_handle();
return IRQ_HANDLED;
}
- if ((-1) == cec_ll_rx(cec_dev->rx_msg))
+ if ((-1) == cec_ll_rx(rx_msg, &rx_len))
return IRQ_HANDLED;
complete(&cec_dev->rx_ok);
/* check rx buffer is full */
- cec_dev->new_msg = 1;
+ new_msg = 1;
mod_delayed_work(cec_dev->cec_thread, dwork, 0);
return IRQ_HANDLED;
}
static void check_wake_up(void)
{
- if (cec_dev->wake_ok == 0)
+ if (wake_ok == 0)
cec_request_active_source();
}
@@ -1404,19 +1642,19 @@ static void check_wake_up(void)
static ssize_t device_type_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", cec_dev->dev_type);
+ return sprintf(buf, "%ld\n", cec_dev->dev_type);
}
static ssize_t device_type_store(struct class *cla,
struct class_attribute *attr, const char *buf, size_t count)
{
- unsigned long type;
+ unsigned int type;
- if (kstrtol(buf, 10, &type))
+ if (kstrtouint(buf, 10, &type) != 1)
return -EINVAL;
cec_dev->dev_type = type;
- CEC_ERR("set dev_type to %ld\n", type);
+ CEC_ERR("set dev_type to %d\n", type);
return count;
}
@@ -1425,9 +1663,9 @@ static ssize_t menu_language_show(struct class *cla,
{
char a, b, c;
- a = ((cec_dev->menu_lang >> 16) & 0xff);
- b = ((cec_dev->menu_lang >> 8) & 0xff);
- c = ((cec_dev->menu_lang >> 0) & 0xff);
+ a = ((cec_dev->cec_info.menu_lang >> 16) & 0xff);
+ b = ((cec_dev->cec_info.menu_lang >> 8) & 0xff);
+ c = ((cec_dev->cec_info.menu_lang >> 0) & 0xff);
return sprintf(buf, "%c%c%c\n", a, b, c);
}
@@ -1439,7 +1677,7 @@ static ssize_t menu_language_store(struct class *cla,
if (sscanf(buf, "%c%c%c", &a, &b, &c) != 3)
return -EINVAL;
- cec_dev->menu_lang = (a << 16) | (b << 8) | c;
+ cec_dev->cec_info.menu_lang = (a << 16) | (b << 8) | c;
CEC_ERR("set menu_language to %s\n", buf);
return count;
}
@@ -1447,17 +1685,17 @@ static ssize_t menu_language_store(struct class *cla,
static ssize_t vendor_id_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "%x\n", cec_dev->vendor_id);
+ return sprintf(buf, "%x\n", cec_dev->cec_info.vendor_id);
}
static ssize_t vendor_id_store(struct class *cla, struct class_attribute *attr,
const char *buf, size_t count)
{
- int id;
+ unsigned int id;
- if (kstrtoint(buf, 16, &id))
+ if (kstrtouint(buf, 16, &id) != 1)
return -EINVAL;
- cec_dev->vendor_id = id;
+ cec_dev->cec_info.vendor_id = id;
return count;
}
@@ -1496,7 +1734,7 @@ static ssize_t dump_reg_show(struct class *cla,
{
int i, s = 0;
- if (cec_dev->ee_cec)
+ if (ee_cec)
return dump_cecrx_reg(b);
s += sprintf(b + s, "TX buffer:\n");
@@ -1528,7 +1766,21 @@ static ssize_t arc_port_show(struct class *cla,
static ssize_t osd_name_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "%s\n", cec_dev->osd_name);
+ return sprintf(buf, "%s\n", cec_dev->cec_info.osd_name);
+}
+
+static ssize_t port_seq_store(struct class *cla,
+ struct class_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int seq;
+
+ if (kstrtouint(buf, 16, &seq) != 1)
+ return -EINVAL;
+
+ CEC_ERR("port_seq:%x\n", seq);
+ cec_dev->port_seq = seq;
+ return count;
}
static ssize_t port_seq_show(struct class *cla,
@@ -1543,7 +1795,7 @@ static ssize_t port_status_show(struct class *cla,
unsigned int tmp;
unsigned int tx_hpd;
- tx_hpd = cec_dev->hpd_state;
+ tx_hpd = cec_dev->tx_dev->hpd_state;
if (cec_dev->dev_type == DEV_TYPE_PLAYBACK) {
tmp = tx_hpd;
return sprintf(buf, "%x\n", tmp);
@@ -1560,17 +1812,17 @@ static ssize_t port_status_show(struct class *cla,
static ssize_t pin_status_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
- unsigned int tx_hpd = 0;
+ unsigned int tx_hpd;
char p;
- tx_hpd = cec_dev->hpd_state;
+ tx_hpd = cec_dev->tx_dev->hpd_state;
if (cec_dev->dev_type == DEV_TYPE_PLAYBACK) {
if (!tx_hpd) {
- cec_dev->pin_status = 0;
+ pin_status = 0;
return sprintf(buf, "%s\n", "disconnected");
}
- if (cec_dev->pin_status == 0) {
- p = (cec_dev->my_log_addr << 4) | CEC_TV_ADDR;
+ if (pin_status == 0) {
+ p = (cec_dev->cec_info.log_addr << 4) | CEC_TV_ADDR;
if (cec_ll_tx(&p, 1) == CEC_FAIL_NONE)
return sprintf(buf, "%s\n", "ok");
else
@@ -1578,8 +1830,7 @@ static ssize_t pin_status_show(struct class *cla,
} else
return sprintf(buf, "%s\n", "ok");
} else {
- return sprintf(buf, "%s\n",
- cec_dev->pin_status ? "ok" : "fail");
+ return sprintf(buf, "%s\n", pin_status ? "ok" : "fail");
}
}
@@ -1597,23 +1848,22 @@ static ssize_t physical_addr_store(struct class *cla,
{
int addr;
- if (kstrtoint(buf, 16, &addr))
+ if (kstrtouint(buf, 16, &addr) != 1)
return -EINVAL;
-
- if (addr > INVALID_PHY_ADDR || addr < 0) {
+ if (addr > 0xffff || addr < 0) {
CEC_ERR("invalid input:%s\n", buf);
- cec_dev->phy_addr_test = 0;
+ phy_addr_test = 0;
return -EINVAL;
}
cec_dev->phy_addr = addr;
- cec_dev->phy_addr_test = 1;
+ phy_addr_test = 1;
return count;
}
static ssize_t dbg_en_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "%x\n", cec_dev->cec_msg_dbg_en);
+ return sprintf(buf, "%x\n", cec_msg_dbg_en);
}
static ssize_t dbg_en_store(struct class *cla, struct class_attribute *attr,
@@ -1621,26 +1871,22 @@ static ssize_t dbg_en_store(struct class *cla, struct class_attribute *attr,
{
int en;
- if (kstrtoint(buf, 10, &en))
+ if (kstrtouint(buf, 16, &en) != 1)
return -EINVAL;
- cec_dev->cec_msg_dbg_en = en ? 1 : 0;
+ cec_msg_dbg_en = en ? 1 : 0;
return count;
}
static ssize_t cmd_store(struct class *cla, struct class_attribute *attr,
const char *bu, size_t count)
{
- char buf[16] = {};
+ char buf[6] = {};
int cnt;
- cnt = sscanf(bu, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
+ cnt = sscanf(bu, "%x %x %x %x %x %x",
(int *)&buf[0], (int *)&buf[1], (int *)&buf[2],
- (int *)&buf[3], (int *)&buf[4], (int *)&buf[5],
- (int *)&buf[6], (int *)&buf[7], (int *)&buf[8],
- (int *)&buf[9], (int *)&buf[10], (int *)&buf[11],
- (int *)&buf[12], (int *)&buf[13], (int *)&buf[14],
- (int *)&buf[15]);
+ (int *)&buf[3], (int *)&buf[4], (int *)&buf[5]);
if (cnt < 0)
return -EINVAL;
cec_ll_tx(buf, cnt);
@@ -1660,7 +1906,7 @@ static ssize_t fun_cfg_store(struct class *cla, struct class_attribute *attr,
{
int cnt, val;
- cnt = kstrtoint(bu, 16, &val);
+ cnt = kstrtouint(bu, 16, &val);
if (cnt < 0 || val > 0xff)
return -EINVAL;
cec_config(val, 1);
@@ -1679,6 +1925,12 @@ static ssize_t fun_cfg_show(struct class *cla,
return sprintf(buf, "0x%x\n", reg & 0xff);
}
+static ssize_t cec_version_show(struct class *cla,
+ struct class_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", cec_dev->cec_info.cec_version);
+}
+
static ssize_t log_addr_store(struct class *cla, struct class_attribute *attr,
const char *bu, size_t count)
{
@@ -1689,8 +1941,8 @@ static ssize_t log_addr_store(struct class *cla, struct class_attribute *attr,
return -EINVAL;
cec_logicaddr_set(val);
/* add by hal, to init some data structure */
- cec_dev->my_log_addr = val;
- cec_dev->power_status = POWER_ON;
+ cec_dev->cec_info.log_addr = val;
+ cec_dev->cec_info.power_status = POWER_ON;
return count;
}
@@ -1698,35 +1950,35 @@ static ssize_t log_addr_store(struct class *cla, struct class_attribute *attr,
static ssize_t log_addr_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "0x%x\n", cec_dev->my_log_addr);
+ return sprintf(buf, "0x%x\n", cec_dev->cec_info.log_addr);
}
static struct class_attribute aocec_class_attr[] = {
__ATTR_WO(cmd),
__ATTR_RO(port_num),
- __ATTR_RO(port_seq),
__ATTR_RO(osd_name),
__ATTR_RO(dump_reg),
__ATTR_RO(port_status),
__ATTR_RO(pin_status),
+ __ATTR_RO(cec_version),
__ATTR_RO(arc_port),
__ATTR_RO(wake_up),
+ __ATTR(port_seq, 0664, port_seq_show, port_seq_store),
__ATTR(physical_addr, 0664, physical_addr_show, physical_addr_store),
__ATTR(vendor_id, 0664, vendor_id_show, vendor_id_store),
__ATTR(menu_language, 0664, menu_language_show, menu_language_store),
__ATTR(device_type, 0664, device_type_show, device_type_store),
__ATTR(dbg_en, 0664, dbg_en_show, dbg_en_store),
- __ATTR(fun_cfg, 0664, fun_cfg_show, fun_cfg_store),
__ATTR(log_addr, 0664, log_addr_show, log_addr_store),
+ __ATTR(fun_cfg, 0664, fun_cfg_show, fun_cfg_store),
__ATTR_NULL
};
/******************** cec hal interface ***************************/
static int hdmitx_cec_open(struct inode *inode, struct file *file)
{
- cec_dev->open_count++;
- if (cec_dev->open_count) {
- cec_dev->hal_control = 1;
+ if (atomic_add_return(1, &cec_dev->cec_info.open_count)) {
+ cec_dev->cec_info.hal_ctl = 1;
/* set default logical addr flag for uboot */
cec_set_reg_bits(AO_DEBUG_REG1, 0xf, 16, 4);
}
@@ -1735,9 +1987,8 @@ static int hdmitx_cec_open(struct inode *inode, struct file *file)
static int hdmitx_cec_release(struct inode *inode, struct file *file)
{
- cec_dev->open_count--;
- if (!cec_dev->open_count)
- cec_dev->hal_control = 0;
+ if (!atomic_sub_return(1, &cec_dev->cec_info.open_count))
+ cec_dev->cec_info.hal_ctl = 0;
return 0;
}
@@ -1747,16 +1998,16 @@ static ssize_t hdmitx_cec_read(struct file *f, char __user *buf,
int ret;
if ((cec_dev->hal_flag & (1 << HDMI_OPTION_SYSTEM_CEC_CONTROL)))
- cec_dev->rx_len = 0;
+ rx_len = 0;
ret = wait_for_completion_timeout(&cec_dev->rx_ok, CEC_FRAME_DELAY);
if (ret <= 0)
return ret;
- if (cec_dev->rx_len == 0)
+ if (rx_len == 0)
return 0;
- if (copy_to_user(buf, cec_dev->rx_msg, cec_dev->rx_len))
+ if (copy_to_user(buf, rx_msg, rx_len))
return -EINVAL;
- return cec_dev->rx_len;
+ return rx_len;
}
static ssize_t hdmitx_cec_write(struct file *f, const char __user *buf,
@@ -1780,15 +2031,21 @@ static ssize_t hdmitx_cec_write(struct file *f, const char __user *buf,
static void init_cec_port_info(struct hdmi_port_info *port,
struct ao_cec_dev *cec_dev)
{
- unsigned int a, b, c;
+ unsigned int a, b, c, d, e = 0;
unsigned int phy_head = 0xf000, phy_app = 0x1000, phy_addr;
+ struct hdmitx_dev *tx_dev;
/* physical address for TV or repeator */
- if (cec_dev->dev_type == DEV_TYPE_TV)
+ tx_dev = cec_dev->tx_dev;
+ if (tx_dev == NULL || cec_dev->dev_type == DEV_TYPE_TV) {
phy_addr = 0;
- else if (cec_dev->phy_addr != INVALID_PHY_ADDR)
- phy_addr = cec_dev->phy_addr;
- else
+ } else if (tx_dev->hdmi_info.vsdb_phy_addr.valid == 1) {
+ a = tx_dev->hdmi_info.vsdb_phy_addr.a;
+ b = tx_dev->hdmi_info.vsdb_phy_addr.b;
+ c = tx_dev->hdmi_info.vsdb_phy_addr.c;
+ d = tx_dev->hdmi_info.vsdb_phy_addr.d;
+ phy_addr = ((a << 12) | (b << 8) | (c << 4) | (d));
+ } else
phy_addr = 0;
/* found physical address append for repeator */
@@ -1805,33 +2062,40 @@ static void init_cec_port_info(struct hdmi_port_info *port,
b = cec_dev->port_num;
/* init for port info */
- for (a = 0; a < b; a++) {
- port[a].type = HDMI_INPUT;
- port[a].port_id = a + 1;
- port[a].cec_supported = 1;
- /* set ARC feature according mask */
- if (cec_dev->arc_port & (1 << a))
- port[a].arc_supported = 1;
- else
- port[a].arc_supported = 0;
-
+ for (a = 0; a < sizeof(cec_dev->port_seq) * 2; a++) {
/* set port physical address according port sequence */
if (cec_dev->port_seq) {
c = (cec_dev->port_seq >> (4 * a)) & 0xf;
- port[a].physical_address = (c + 1) * phy_app + phy_addr;
+ if (c == 0xf) { /* not used */
+ CEC_INFO("port %d is not used\n", a);
+ continue;
+ } else if (!c)
+ break;
+ port[e].physical_address = (c) * phy_app + phy_addr;
} else {
/* asending order if port_seq is not set */
- port[a].physical_address = (a + 1) * phy_app + phy_addr;
+ port[e].physical_address = (e + 1) * phy_app + phy_addr;
}
+ port[e].type = HDMI_INPUT;
+ port[e].port_id = a + 1;
+ port[e].cec_supported = 1;
+ /* set ARC feature according mask */
+ if (cec_dev->arc_port & (1 << a))
+ port[e].arc_supported = 1;
+ else
+ port[e].arc_supported = 0;
+ e++;
+ if (e >= b)
+ break;
}
if (cec_dev->dev_type == DEV_TYPE_TUNER) {
/* last port is for tx in mixed tx/rx */
- port[a].type = HDMI_OUTPUT;
- port[a].port_id = a + 1;
- port[a].cec_supported = 1;
- port[a].arc_supported = 0;
- port[a].physical_address = phy_addr;
+ port[e].type = HDMI_OUTPUT;
+ port[e].port_id = 0; /* 0 for tx port id */
+ port[e].cec_supported = 1;
+ port[e].arc_supported = 0;
+ port[e].physical_address = phy_addr;
}
}
@@ -1839,80 +2103,112 @@ static long hdmitx_cec_ioctl(struct file *f,
unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
- unsigned long tmp = 0, i;
+ unsigned long tmp;
struct hdmi_port_info *port;
- int tx_hpd = 0;
+ int a, b, c, d;
+ struct hdmitx_dev *tx_dev;
+ int tx_hpd;
+ mutex_lock(&cec_dev->cec_ioctl_mutex);
switch (cmd) {
case CEC_IOC_GET_PHYSICAL_ADDR:
check_physical_addr_valid(20);
- if (cec_dev->dev_type == DEV_TYPE_PLAYBACK &&
- !cec_dev->phy_addr_test) {
+ if (cec_dev->dev_type == DEV_TYPE_PLAYBACK && !phy_addr_test) {
/* physical address for mbox */
- if (cec_dev->phy_addr == INVALID_PHY_ADDR)
+ if (cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.valid
+ == 0) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
- tmp = cec_dev->phy_addr;
+ }
+ a = cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.a;
+ b = cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.b;
+ c = cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.c;
+ d = cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.d;
+ tmp = ((a << 12) | (b << 8) | (c << 4) | (d << 0));
} else {
- if (cec_dev->dev_type == DEV_TYPE_TV)
+ /* physical address for TV or repeator */
+ tx_dev = cec_dev->tx_dev;
+ if (!tx_dev || cec_dev->dev_type == DEV_TYPE_TV) {
tmp = 0;
- /* for repeator */
- else if (cec_dev->phy_addr != INVALID_PHY_ADDR)
- tmp = cec_dev->phy_addr;
- else
+ } else if (tx_dev->hdmi_info.vsdb_phy_addr.valid == 1) {
+ a = tx_dev->hdmi_info.vsdb_phy_addr.a;
+ b = tx_dev->hdmi_info.vsdb_phy_addr.b;
+ c = tx_dev->hdmi_info.vsdb_phy_addr.c;
+ d = tx_dev->hdmi_info.vsdb_phy_addr.d;
+ tmp = ((a << 12) | (b << 8) | (c << 4) | (d));
+ } else
tmp = 0;
}
- if (!cec_dev->phy_addr_test) {
+ if (!phy_addr_test) {
cec_dev->phy_addr = tmp;
cec_phyaddr_config(tmp, 1);
} else
tmp = cec_dev->phy_addr;
- if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd)))
+ if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd))) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
+ }
break;
case CEC_IOC_GET_VERSION:
- tmp = cec_dev->cec_version;
- if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd)))
+ tmp = cec_dev->cec_info.cec_version;
+ if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd))) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
+ }
break;
case CEC_IOC_GET_VENDOR_ID:
- tmp = cec_dev->vendor_id;
- if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd)))
+ tmp = cec_dev->v_data.vendor_id;
+ if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd))) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
+ }
break;
case CEC_IOC_GET_PORT_NUM:
tmp = cec_dev->port_num;
- if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd)))
+ if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd))) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
+ }
break;
case CEC_IOC_GET_PORT_INFO:
port = kcalloc(cec_dev->port_num, sizeof(*port), GFP_KERNEL);
if (!port) {
CEC_ERR("no memory\n");
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
}
+ check_physical_addr_valid(20);
if (cec_dev->dev_type == DEV_TYPE_PLAYBACK) {
/* for tx only 1 port */
- tmp = cec_dev->phy_addr;
+ a = cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.a;
+ b = cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.b;
+ c = cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.c;
+ d = cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.d;
+ tmp = ((a << 12) | (b << 8) | (c << 4) | (d << 0));
+ if (cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.valid == 0)
+ tmp = 0xffff;
port->type = HDMI_OUTPUT;
- port->port_id = 1;
+ port->port_id = 0;
port->cec_supported = 1;
/* not support arc for tx */
port->arc_supported = 0;
- port->physical_address = tmp & INVALID_PHY_ADDR;
+ port->physical_address = tmp & 0xffff;
if (copy_to_user(argp, port, sizeof(*port))) {
kfree(port);
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
}
} else {
- tmp = cec_dev->port_num;
+ b = cec_dev->port_num;
init_cec_port_info(port, cec_dev);
- if (copy_to_user(argp, port, sizeof(*port) * tmp)) {
+ if (copy_to_user(argp, port, sizeof(*port) * b)) {
kfree(port);
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
}
}
@@ -1958,54 +2254,67 @@ static long hdmitx_cec_ioctl(struct file *f,
break;
case CEC_IOC_SET_OPTION_SET_LANG:
- cec_dev->menu_lang = arg;
+ cec_dev->cec_info.menu_lang = arg;
break;
case CEC_IOC_GET_CONNECT_STATUS:
- tx_hpd = cec_dev->hpd_state;
+ tx_hpd = cec_dev->tx_dev->hpd_state;
if (cec_dev->dev_type == DEV_TYPE_PLAYBACK)
tmp = tx_hpd;
else {
- if (copy_from_user(&i, argp, _IOC_SIZE(cmd)))
+ if (copy_from_user(&a, argp, _IOC_SIZE(cmd))) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
- if (cec_dev->port_num == i &&
- cec_dev->dev_type == DEV_TYPE_TUNER)
+ }
+ if (!a && cec_dev->dev_type == DEV_TYPE_TUNER)
tmp = tx_hpd;
else { /* mixed for rx */
tmp = (hdmirx_rd_top(TOP_HPD_PWR5V) >> 20);
- if (tmp & (1 << (i - 1)))
+ if (tmp & (1 << (a - 1)))
tmp = 1;
else
tmp = 0;
}
}
- if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd)))
+ if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd))) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
+ }
break;
case CEC_IOC_ADD_LOGICAL_ADDR:
tmp = arg & 0xf;
cec_logicaddr_set(tmp);
/* add by hal, to init some data structure */
- cec_dev->my_log_addr = tmp;
- if (cec_dev->dev_type != DEV_TYPE_PLAYBACK)
+ cec_dev->cec_info.log_addr = tmp;
+ cec_dev->cec_info.power_status = POWER_ON;
+
+ cec_dev->cec_info.vendor_id = cec_dev->v_data.vendor_id;
+ strcpy(cec_dev->cec_info.osd_name,
+ cec_dev->v_data.cec_osd_string);
+
+ if (cec_dev->dev_type == DEV_TYPE_PLAYBACK)
+ cec_dev->cec_info.menu_status = DEVICE_MENU_ACTIVE;
+ else
check_wake_up();
break;
case CEC_IOC_CLR_LOGICAL_ADDR:
- /* TODO: clear global info */
+ cec_clear_logical_addr();
break;
case CEC_IOC_SET_DEV_TYPE:
- if (arg < DEV_TYPE_TV && arg > DEV_TYPE_VIDEO_PROCESSOR)
+ if (arg > DEV_TYPE_VIDEO_PROCESSOR) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
+ }
cec_dev->dev_type = arg;
break;
case CEC_IOC_SET_ARC_ENABLE:
/* select arc according arg */
if (arg)
- hdmirx_wr_top(TOP_ARCTX_CNTL, 0x03);
+ hdmirx_wr_top(TOP_ARCTX_CNTL, 0x01);
else
hdmirx_wr_top(TOP_ARCTX_CNTL, 0x00);
CEC_INFO("set arc en:%ld, reg:%lx\n",
@@ -2015,6 +2324,7 @@ static long hdmitx_cec_ioctl(struct file *f,
default:
break;
}
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return 0;
}
@@ -2030,9 +2340,11 @@ static long hdmitx_cec_compat_ioctl(struct file *f,
/* for improve rw permission */
static char *aml_cec_class_devnode(struct device *dev, umode_t *mode)
{
- if (mode)
+ if (mode) {
*mode = 0666;
- CEC_INFO("mode is %x\n", *mode);
+ CEC_INFO("mode is %x\n", *mode);
+ } else
+ CEC_INFO("mode is null\n");
return NULL;
}
@@ -2056,8 +2368,7 @@ static const struct file_operations hdmitx_cec_fops = {
};
/************************ cec high level code *****************************/
-#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
-struct early_suspend aocec_suspend_handler;
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void aocec_early_suspend(struct early_suspend *h)
{
cec_dev->cec_suspend = CEC_EARLY_SUSPEND;
@@ -2066,120 +2377,162 @@ static void aocec_early_suspend(struct early_suspend *h)
static void aocec_late_resume(struct early_suspend *h)
{
- cec_dev->cec_suspend = 0;
+ cec_dev->cec_suspend = CEC_POWER_ON;
CEC_INFO("%s, suspend:%d\n", __func__, cec_dev->cec_suspend);
+
}
+#endif
+
+#ifdef CONFIG_OF
+static const struct cec_platform_data_s cec_gxl_data = {
+ .line_bit = 8,
+ .ee_to_ao = 0,
+};
-#endif //CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
+static const struct cec_platform_data_s cec_txlx_data = {
+ .line_bit = 7,
+ .ee_to_ao = 1,
+};
+
+static const struct cec_platform_data_s cec_g12a_data = {
+ .line_bit = 7,
+ .ee_to_ao = 1,
+};
+
+static const struct of_device_id aml_cec_dt_match[] = {
+ {
+ .compatible = "amlogic, amlogic-aocec",
+ .data = &cec_gxl_data,
+ },
+ {
+ .compatible = "amlogic, aocec-txlx",
+ .data = &cec_txlx_data,
+ },
+ {
+ .compatible = "amlogic, aocec-g12a",
+ .data = &cec_g12a_data,
+ },
+};
+#endif
static int aml_cec_probe(struct platform_device *pdev)
{
struct device *cdev;
+ int ret = 0;
+ const struct of_device_id *of_id;
#ifdef CONFIG_OF
struct device_node *node = pdev->dev.of_node;
- unsigned int tmp;
- int irq_idx = 0, r, num;
+ int irq_idx = 0, r;
const char *irq_name = NULL;
struct pinctrl *p;
+ struct vendor_info_data *vend;
struct resource *res;
resource_size_t *base;
#endif
- cec_dev = kzalloc(sizeof(struct ao_cec_dev), GFP_KERNEL);
- if (!cec_dev)
- return -ENOMEM;
+ cec_dev = devm_kzalloc(&pdev->dev, sizeof(struct ao_cec_dev),
+ GFP_KERNEL);
+ if (!cec_dev) {
+ CEC_ERR("device malloc err!\n");
+ ret = -ENOMEM;
+ goto tag_cec_devm_err;
+ }
+ CEC_ERR("cec driver date:%s\n", CEC_DRIVER_VERSION);
cec_dev->dev_type = DEV_TYPE_PLAYBACK;
cec_dev->dbg_dev = &pdev->dev;
- cec_dev->wake_ok = 1;
- cec_dev->phy_addr = INVALID_PHY_ADDR;
+ cec_dev->tx_dev = get_hdmitx_device();
+ cec_dev->cpu_type = get_cpu_type();
+ phy_addr_test = 0;
/* cdev registe */
r = class_register(&aocec_class);
if (r) {
CEC_ERR("regist class failed\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto tag_cec_class_reg;
}
pdev->dev.class = &aocec_class;
- cec_dev->dev_no = register_chrdev(0, CEC_DEV_NAME,
+ r = register_chrdev(0, CEC_DEV_NAME,
&hdmitx_cec_fops);
- if (cec_dev->dev_no < 0) {
+ if (r < 0) {
CEC_ERR("alloc chrdev failed\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto tag_cec_chr_reg_err;
}
- CEC_INFO("alloc chrdev %x\n", cec_dev->dev_no);
+ cec_dev->cec_info.dev_no = r;
+ CEC_INFO("alloc chrdev %x\n", cec_dev->cec_info.dev_no);
cdev = device_create(&aocec_class, &pdev->dev,
- MKDEV(cec_dev->dev_no, 0),
+ MKDEV(cec_dev->cec_info.dev_no, 0),
NULL, CEC_DEV_NAME);
if (IS_ERR(cdev)) {
CEC_ERR("create chrdev failed, dev:%p\n", cdev);
- unregister_chrdev(cec_dev->dev_no,
- CEC_DEV_NAME);
- return -EINVAL;
+ ret = -EINVAL;
+ goto tag_cec_device_create_err;
}
+ /*get compatible matched device, to get chip related data*/
+ of_id = of_match_device(aml_cec_dt_match, &pdev->dev);
+ if (!of_id)
+ CEC_ERR("unable to get matched device\n");
+ cec_dev->plat_data = (struct cec_platform_data_s *)of_id->data;
+
+ cec_dev->cec_info.open_count.counter = 0;
init_completion(&cec_dev->rx_ok);
init_completion(&cec_dev->tx_ok);
mutex_init(&cec_dev->cec_mutex);
+ mutex_init(&cec_dev->cec_ioctl_mutex);
spin_lock_init(&cec_dev->cec_reg_lock);
cec_dev->cec_thread = create_workqueue("cec_work");
if (cec_dev->cec_thread == NULL) {
CEC_INFO("create work queue failed\n");
- return -EFAULT;
+ ret = -EFAULT;
+ goto tag_cec_threat_err;
}
INIT_DELAYED_WORK(&cec_dev->cec_work, cec_task);
- cec_dev->remote_cec_dev = input_allocate_device();
- if (!cec_dev->remote_cec_dev)
+ cec_dev->cec_info.remote_cec_dev = input_allocate_device();
+ if (!cec_dev->cec_info.remote_cec_dev) {
CEC_INFO("No enough memory\n");
+ ret = -ENOMEM;
+ goto tag_cec_alloc_input_err;
+ }
- cec_dev->remote_cec_dev->name = "cec_input";
+ cec_dev->cec_info.remote_cec_dev->name = "cec_input";
- cec_dev->remote_cec_dev->evbit[0] = BIT_MASK(EV_KEY);
- cec_dev->remote_cec_dev->keybit[BIT_WORD(BTN_0)] =
+ cec_dev->cec_info.remote_cec_dev->evbit[0] = BIT_MASK(EV_KEY);
+ cec_dev->cec_info.remote_cec_dev->keybit[BIT_WORD(BTN_0)] =
BIT_MASK(BTN_0);
- cec_dev->remote_cec_dev->id.bustype = BUS_ISA;
- cec_dev->remote_cec_dev->id.vendor = 0x1b8e;
- cec_dev->remote_cec_dev->id.product = 0x0cec;
- cec_dev->remote_cec_dev->id.version = 0x0001;
+ cec_dev->cec_info.remote_cec_dev->id.bustype = BUS_ISA;
+ cec_dev->cec_info.remote_cec_dev->id.vendor = 0x1b8e;
+ cec_dev->cec_info.remote_cec_dev->id.product = 0x0cec;
+ cec_dev->cec_info.remote_cec_dev->id.version = 0x0001;
- set_bit(KEY_POWER, cec_dev->remote_cec_dev->keybit);
+ set_bit(KEY_POWER, cec_dev->cec_info.remote_cec_dev->keybit);
- if (input_register_device(cec_dev->remote_cec_dev)) {
+ if (input_register_device(cec_dev->cec_info.remote_cec_dev)) {
CEC_INFO("Failed to register device\n");
- input_free_device(cec_dev->remote_cec_dev);
+ input_free_device(cec_dev->cec_info.remote_cec_dev);
}
#ifdef CONFIG_OF
/* if using EE CEC */
if (of_property_read_bool(node, "ee_cec"))
- cec_dev->ee_cec = 1;
+ ee_cec = 1;
else
- cec_dev->ee_cec = 0;
- CEC_INFO("using EE cec:%d\n", cec_dev->ee_cec);
-
+ ee_cec = 0;
+ CEC_INFO("using EE cec:%d\n", ee_cec);
/* pinmux set */
if (of_get_property(node, "pinctrl-names", NULL)) {
r = of_property_read_string(node,
"pinctrl-names",
&cec_dev->pin_name);
- if (!r)
+ if ((!r) && strcmp(cec_dev->pin_name, "default")) {
+ CEC_INFO("%s pin name:%s\n", __func__,
+ cec_dev->pin_name);
p = devm_pinctrl_get_select(&pdev->dev,
cec_dev->pin_name);
- }
-
- /* irq set */
- irq_idx = of_irq_get(node, 0);
- cec_dev->irq_cec = irq_idx;
- if (of_get_property(node, "interrupt-names", NULL)) {
- r = of_property_read_string(node, "interrupt-names", &irq_name);
- if (!r && !cec_dev->ee_cec) {
- r = request_irq(irq_idx, &cec_isr_handler, IRQF_SHARED,
- irq_name, (void *)cec_dev);
- }
- if (!r && cec_dev->ee_cec) {
- r = request_irq(irq_idx, &cecrx_isr, IRQF_SHARED,
- irq_name, (void *)cec_dev);
}
}
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res) {
base = ioremap(res->start, res->end - res->start);
@@ -2212,86 +2565,118 @@ static int aml_cec_probe(struct platform_device *pdev)
CEC_ERR("no hhi reg resource\n");
cec_dev->hhi_reg = NULL;
}
-
- r = of_property_read_u32(node, "port_num", &num);
+ r = of_property_read_u32(node, "port_num", &(cec_dev->port_num));
if (r) {
CEC_ERR("not find 'port_num'\n");
cec_dev->port_num = 1;
- } else
- cec_dev->port_num = num;
- r = of_property_read_u32(node, "arc_port_mask", &num);
+ }
+ r = of_property_read_u32(node, "arc_port_mask", &(cec_dev->arc_port));
if (r) {
CEC_ERR("not find 'arc_port_mask'\n");
cec_dev->arc_port = 0;
- } else
- cec_dev->arc_port = num;
+ }
+
+ vend = &cec_dev->v_data;
+ r = of_property_read_string(node, "vendor_name",
+ (const char **)&(vend->vendor_name));
+ if (r)
+ CEC_INFO("not find vendor name\n");
- r = of_property_read_u32(node, "vendor_id", &(cec_dev->vendor_id));
+ r = of_property_read_u32(node, "vendor_id", &(vend->vendor_id));
if (r)
CEC_INFO("not find vendor id\n");
+ r = of_property_read_string(node, "product_desc",
+ (const char **)&(vend->product_desc));
+ if (r)
+ CEC_INFO("not find product desc\n");
+
r = of_property_read_string(node, "cec_osd_string",
- (const char **)&(cec_dev->osd_name));
+ (const char **)&(vend->cec_osd_string));
if (r) {
CEC_INFO("not find cec osd string\n");
- cec_dev->osd_name = "Amlogic";
+ strcpy(vend->cec_osd_string, "AML TV/BOX");
}
-
r = of_property_read_u32(node, "cec_version",
- &(tmp));
+ &(cec_dev->cec_info.cec_version));
if (r) {
/* default set to 2.0 */
CEC_INFO("not find cec_version\n");
- cec_dev->cec_version = CEC_VERSION_20;
- } else
- cec_dev->cec_version = tmp;
+ cec_dev->cec_info.cec_version = CEC_VERSION_20;
+ }
- /* get port sequence */
- node = of_find_node_by_path("/hdmirx");
- if (node == NULL) {
- CEC_ERR("can't find hdmirx\n");
- cec_dev->port_seq = 0;
- } else {
- r = of_property_read_u32(node, "rx_port_maps",
- &(cec_dev->port_seq));
- if (r)
- CEC_INFO("not find rx_port_maps\n");
+ /* irq set */
+ cec_irq_enable(false);
+ irq_idx = of_irq_get(node, 0);
+ cec_dev->irq_cec = irq_idx;
+ if (of_get_property(node, "interrupt-names", NULL)) {
+ r = of_property_read_string(node, "interrupt-names", &irq_name);
+ if (!r && !ee_cec) {
+ r = request_irq(irq_idx, &cec_isr_handler, IRQF_SHARED,
+ irq_name, (void *)cec_dev);
+ }
+ if (!r && ee_cec) {
+ r = request_irq(irq_idx, &cecrx_isr, IRQF_SHARED,
+ irq_name, (void *)cec_dev);
+ }
}
#endif
-#ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
+ if (!ee_cec) {
+ last_cec_msg = devm_kzalloc(&pdev->dev,
+ sizeof(*last_cec_msg), GFP_KERNEL);
+ if (!last_cec_msg) {
+ CEC_ERR("allocate last_cec_msg failed\n");
+ ret = -ENOMEM;
+ goto tag_cec_msg_alloc_err;
+ }
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
aocec_suspend_handler.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
aocec_suspend_handler.suspend = aocec_early_suspend;
aocec_suspend_handler.resume = aocec_late_resume;
aocec_suspend_handler.param = cec_dev;
register_early_suspend(&aocec_suspend_handler);
#endif
- device_init_wakeup(cec_dev->dbg_dev, 1);
-
- hrtimer_init(&cec_dev->start_bit_check,
- CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- cec_dev->start_bit_check.function = cec_line_check;
- cec_dev->cec_msg_dbg_en = DEFAULT_DEBUG_EN;
- cec_dev->hdmitx_nb.notifier_call = cec_hdmi_tx_notify_handler;
- hdmitx_event_notifier_regist(&cec_dev->hdmitx_nb);
+ hrtimer_init(&start_bit_check, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ start_bit_check.function = cec_line_check;
/* for init */
cec_pre_init();
queue_delayed_work(cec_dev->cec_thread, &cec_dev->cec_work, 0);
+
+ CEC_ERR("%s success end\n", __func__);
+
return 0;
+tag_cec_msg_alloc_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));
+tag_cec_device_create_err:
+ unregister_chrdev(cec_dev->cec_info.dev_no, CEC_DEV_NAME);
+tag_cec_chr_reg_err:
+ class_unregister(&aocec_class);
+tag_cec_class_reg:
+ devm_kfree(&pdev->dev, cec_dev);
+tag_cec_devm_err:
+ return ret;
}
-static __exit int aml_cec_remove(struct platform_device *pdev)
+static int aml_cec_remove(struct platform_device *pdev)
{
CEC_INFO("cec uninit!\n");
free_irq(cec_dev->irq_cec, (void *)cec_dev);
+ kfree(last_cec_msg);
- hdmitx_event_notifier_unregist(&cec_dev->hdmitx_nb);
if (cec_dev->cec_thread) {
cancel_delayed_work_sync(&cec_dev->cec_work);
destroy_workqueue(cec_dev->cec_thread);
}
- input_unregister_device(cec_dev->remote_cec_dev);
- unregister_chrdev(cec_dev->dev_no, CEC_DEV_NAME);
+ 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);
kfree(cec_dev);
return 0;
@@ -2317,57 +2702,25 @@ static void aml_cec_pm_complete(struct device *dev)
cec_key_report(0);
}
-static int aml_cec_suspend_late(struct device *dev)
+static int aml_cec_suspend_noirq(struct device *dev)
{
- struct pinctrl *p;
- struct pinctrl_state *s;
- int ret;
-
- CEC_INFO("%s!\n", __func__);
- if (cec_dev->ee_cec) {
- p = devm_pinctrl_get(cec_dev->dbg_dev);
- if (IS_ERR(p))
- return -EINVAL;
- s = pinctrl_lookup_state(p, "dummy");
- ret = pinctrl_select_state(p, s);
- if (ret < 0)
- devm_pinctrl_put(p);
- CEC_INFO("%s, unselect pin mux\n", __func__);
- return ret;
- }
return 0;
}
-static int aml_cec_resume_early(struct device *dev)
+static int aml_cec_resume_noirq(struct device *dev)
{
- struct pinctrl *p;
+ CEC_INFO("cec resume noirq!\n");
+ cec_dev->cec_info.power_status = TRANS_STANDBY_TO_ON;
+ cec_dev->cec_suspend = CEC_POWER_RESUME;
- CEC_INFO("%s!\n", __func__);
- cec_dev->power_status = TRANS_STANDBY_TO_ON;
-
- /* reselect pin mux if resume */
- if (cec_dev->ee_cec) {
- p = devm_pinctrl_get_select(cec_dev->dbg_dev,
- cec_dev->pin_name);
- CEC_INFO("%s, reselect pin:%p\n", __func__, p);
- }
return 0;
}
static const struct dev_pm_ops aml_cec_pm = {
.prepare = aml_cec_pm_prepare,
.complete = aml_cec_pm_complete,
- .suspend_late = aml_cec_suspend_late,
- .resume_early = aml_cec_resume_early,
-};
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id aml_cec_dt_match[] = {
- {
- .compatible = "amlogic, amlogic-aocec",
- },
- {},
+ .suspend_noirq = aml_cec_suspend_noirq,
+ .resume_noirq = aml_cec_resume_noirq,
};
#endif
@@ -2399,7 +2752,6 @@ static void __exit cec_uninit(void)
platform_driver_unregister(&aml_cec_driver);
}
-
module_init(cec_init);
module_exit(cec_uninit);
MODULE_DESCRIPTION("AMLOGIC HDMI TX CEC driver");
diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h
index 4b185e9..551b089 100644
--- a/drivers/amlogic/cec/hdmi_ao_cec.h
+++ b/drivers/amlogic/cec/hdmi_ao_cec.h
@@ -18,8 +18,7 @@
#ifndef __AO_CEC_H__
#define __AO_CEC_H__
-#include "ao_cec_reg.h"
-#include "ee_cec_reg.h"
+#define CEC_DRIVER_VERSION "2018/02/22\n"
#define CEC_FRAME_DELAY msecs_to_jiffies(400)
#define CEC_DEV_NAME "cec"
@@ -29,7 +28,361 @@
#define HR_DELAY(n) (ktime_set(0, n * 1000 * 1000))
-#ifdef CONFIG_TVIN_HDMI
+#define CEC_FUNC_MASK 0
+#define ONE_TOUCH_PLAY_MASK 1
+#define ONE_TOUCH_STANDBY_MASK 2
+#define AUTO_POWER_ON_MASK 3
+
+
+#define AO_BASE 0xc8100000
+
+#define AO_GPIO_I ((0x0A << 2))
+
+#define AO_CEC_GEN_CNTL ((0x40 << 2))
+#define AO_CEC_RW_REG ((0x41 << 2))
+#define AO_CEC_INTR_MASKN ((0x42 << 2))
+#define AO_CEC_INTR_CLR ((0x43 << 2))
+#define AO_CEC_INTR_STAT ((0x44 << 2))
+
+#define AO_RTI_PWR_CNTL_REG0 ((0x04 << 2))
+#define AO_CRT_CLK_CNTL1 ((0x1a << 2))
+#define AO_RTC_ALT_CLK_CNTL0 ((0x25 << 2))
+#define AO_RTC_ALT_CLK_CNTL1 ((0x26 << 2))
+
+/* for TXLX, same as AO_RTC_ALT_CLK_CNTLx */
+#define AO_CEC_CLK_CNTL_REG0 ((0x1d << 2))
+#define AO_CEC_CLK_CNTL_REG1 ((0x1e << 2))
+
+#define AO_RTI_STATUS_REG1 ((0x01 << 2))
+#define AO_DEBUG_REG0 ((0x28 << 2))
+#define AO_DEBUG_REG1 ((0x29 << 2))
+#define AO_DEBUG_REG2 ((0x2a << 2))
+#define AO_DEBUG_REG3 ((0x2b << 2))
+#define AO_CEC_STICKY_DATA0 ((0xca << 2))
+#define AO_CEC_STICKY_DATA1 ((0xcb << 2))
+#define AO_CEC_STICKY_DATA2 ((0xcc << 2))
+#define AO_CEC_STICKY_DATA3 ((0xcd << 2))
+#define AO_CEC_STICKY_DATA4 ((0xce << 2))
+#define AO_CEC_STICKY_DATA5 ((0xcf << 2))
+#define AO_CEC_STICKY_DATA6 ((0xd0 << 2))
+#define AO_CEC_STICKY_DATA7 ((0xd1 << 2))
+
+/*
+ * AOCEC_B
+ */
+#define AO_CECB_CLK_CNTL_REG0 ((0xa0 << 2))
+#define AO_CECB_CLK_CNTL_REG1 ((0xa1 << 2))
+#define AO_CECB_GEN_CNTL ((0xa2 << 2))
+#define AO_CECB_RW_REG ((0xa3 << 2))
+#define AO_CECB_INTR_MASKN ((0xa4 << 2))
+#define AO_CECB_INTR_CLR ((0xa5 << 2))
+#define AO_CECB_INTR_STAT ((0xa6 << 2))
+
+/* read/write */
+#define CEC_TX_MSG_0_HEADER 0x00
+#define CEC_TX_MSG_1_OPCODE 0x01
+#define CEC_TX_MSG_2_OP1 0x02
+#define CEC_TX_MSG_3_OP2 0x03
+#define CEC_TX_MSG_4_OP3 0x04
+#define CEC_TX_MSG_5_OP4 0x05
+#define CEC_TX_MSG_6_OP5 0x06
+#define CEC_TX_MSG_7_OP6 0x07
+#define CEC_TX_MSG_8_OP7 0x08
+#define CEC_TX_MSG_9_OP8 0x09
+#define CEC_TX_MSG_A_OP9 0x0A
+#define CEC_TX_MSG_B_OP10 0x0B
+#define CEC_TX_MSG_C_OP11 0x0C
+#define CEC_TX_MSG_D_OP12 0x0D
+#define CEC_TX_MSG_E_OP13 0x0E
+#define CEC_TX_MSG_F_OP14 0x0F
+
+/* read/write */
+#define CEC_TX_MSG_LENGTH 0x10
+#define CEC_TX_MSG_CMD 0x11
+#define CEC_TX_WRITE_BUF 0x12
+#define CEC_TX_CLEAR_BUF 0x13
+#define CEC_RX_MSG_CMD 0x14
+#define CEC_RX_CLEAR_BUF 0x15
+#define CEC_LOGICAL_ADDR0 0x16
+#define CEC_LOGICAL_ADDR1 0x17
+#define CEC_LOGICAL_ADDR2 0x18
+#define CEC_LOGICAL_ADDR3 0x19
+#define CEC_LOGICAL_ADDR4 0x1A
+#define CEC_CLOCK_DIV_H 0x1B
+#define CEC_CLOCK_DIV_L 0x1C
+
+/* The following registers are for fine tuning CEC bit timing parameters.
+ * They are only valid in AO CEC, NOT valid in HDMITX CEC.
+ * The AO CEC's timing parameters are already set default to work with
+ * 32768Hz clock, so hopefully SW never need to program these registers.
+ * The timing registers are made programmable just in case.
+ */
+#define AO_CEC_QUIESCENT_25MS_BIT7_0 0x20
+#define AO_CEC_QUIESCENT_25MS_BIT11_8 0x21
+#define AO_CEC_STARTBITMINL2H_3MS5_BIT7_0 0x22
+#define AO_CEC_STARTBITMINL2H_3MS5_BIT8 0x23
+#define AO_CEC_STARTBITMAXL2H_3MS9_BIT7_0 0x24
+#define AO_CEC_STARTBITMAXL2H_3MS9_BIT8 0x25
+#define AO_CEC_STARTBITMINH_0MS6_BIT7_0 0x26
+#define AO_CEC_STARTBITMINH_0MS6_BIT8 0x27
+#define AO_CEC_STARTBITMAXH_1MS0_BIT7_0 0x28
+#define AO_CEC_STARTBITMAXH_1MS0_BIT8 0x29
+#define AO_CEC_STARTBITMINTOTAL_4MS3_BIT7_0 0x2A
+#define AO_CEC_STARTBITMINTOTAL_4MS3_BIT9_8 0x2B
+#define AO_CEC_STARTBITMAXTOTAL_4MS7_BIT7_0 0x2C
+#define AO_CEC_STARTBITMAXTOTAL_4MS7_BIT9_8 0x2D
+#define AO_CEC_LOGIC1MINL2H_0MS4_BIT7_0 0x2E
+#define AO_CEC_LOGIC1MINL2H_0MS4_BIT8 0x2F
+#define AO_CEC_LOGIC1MAXL2H_0MS8_BIT7_0 0x30
+#define AO_CEC_LOGIC1MAXL2H_0MS8_BIT8 0x31
+#define AO_CEC_LOGIC0MINL2H_1MS3_BIT7_0 0x32
+#define AO_CEC_LOGIC0MINL2H_1MS3_BIT8 0x33
+#define AO_CEC_LOGIC0MAXL2H_1MS7_BIT7_0 0x34
+#define AO_CEC_LOGIC0MAXL2H_1MS7_BIT8 0x35
+#define AO_CEC_LOGICMINTOTAL_2MS05_BIT7_0 0x36
+#define AO_CEC_LOGICMINTOTAL_2MS05_BIT9_8 0x37
+#define AO_CEC_LOGICMAXHIGH_2MS8_BIT7_0 0x38
+#define AO_CEC_LOGICMAXHIGH_2MS8_BIT8 0x39
+#define AO_CEC_LOGICERRLOW_3MS4_BIT7_0 0x3A
+#define AO_CEC_LOGICERRLOW_3MS4_BIT8 0x3B
+#define AO_CEC_NOMSMPPOINT_1MS05 0x3C
+#define AO_CEC_DELCNTR_LOGICERR 0x3E
+#define AO_CEC_TXTIME_17MS_BIT7_0 0x40
+#define AO_CEC_TXTIME_17MS_BIT10_8 0x41
+#define AO_CEC_TXTIME_2BIT_BIT7_0 0x42
+#define AO_CEC_TXTIME_2BIT_BIT10_8 0x43
+#define AO_CEC_TXTIME_4BIT_BIT7_0 0x44
+#define AO_CEC_TXTIME_4BIT_BIT10_8 0x45
+#define AO_CEC_STARTBITNOML2H_3MS7_BIT7_0 0x46
+#define AO_CEC_STARTBITNOML2H_3MS7_BIT8 0x47
+#define AO_CEC_STARTBITNOMH_0MS8_BIT7_0 0x48
+#define AO_CEC_STARTBITNOMH_0MS8_BIT8 0x49
+#define AO_CEC_LOGIC1NOML2H_0MS6_BIT7_0 0x4A
+#define AO_CEC_LOGIC1NOML2H_0MS6_BIT8 0x4B
+#define AO_CEC_LOGIC0NOML2H_1MS5_BIT7_0 0x4C
+#define AO_CEC_LOGIC0NOML2H_1MS5_BIT8 0x4D
+#define AO_CEC_LOGIC1NOMH_1MS8_BIT7_0 0x4E
+#define AO_CEC_LOGIC1NOMH_1MS8_BIT8 0x4F
+#define AO_CEC_LOGIC0NOMH_0MS9_BIT7_0 0x50
+#define AO_CEC_LOGIC0NOMH_0MS9_BIT8 0x51
+#define AO_CEC_LOGICERRLOW_3MS6_BIT7_0 0x52
+#define AO_CEC_LOGICERRLOW_3MS6_BIT8 0x53
+#define AO_CEC_CHKCONTENTION_0MS1 0x54
+#define AO_CEC_PREPARENXTBIT_0MS05_BIT7_0 0x56
+#define AO_CEC_PREPARENXTBIT_0MS05_BIT8 0x57
+#define AO_CEC_NOMSMPACKPOINT_0MS45 0x58
+#define AO_CEC_ACK0NOML2H_1MS5_BIT7_0 0x5A
+#define AO_CEC_ACK0NOML2H_1MS5_BIT8 0x5B
+
+#define AO_CEC_BUGFIX_DISABLE_0 0x60
+#define AO_CEC_BUGFIX_DISABLE_1 0x61
+
+/* read only */
+#define CEC_RX_MSG_0_HEADER 0x80
+#define CEC_RX_MSG_1_OPCODE 0x81
+#define CEC_RX_MSG_2_OP1 0x82
+#define CEC_RX_MSG_3_OP2 0x83
+#define CEC_RX_MSG_4_OP3 0x84
+#define CEC_RX_MSG_5_OP4 0x85
+#define CEC_RX_MSG_6_OP5 0x86
+#define CEC_RX_MSG_7_OP6 0x87
+#define CEC_RX_MSG_8_OP7 0x88
+#define CEC_RX_MSG_9_OP8 0x89
+#define CEC_RX_MSG_A_OP9 0x8A
+#define CEC_RX_MSG_B_OP10 0x8B
+#define CEC_RX_MSG_C_OP11 0x8C
+#define CEC_RX_MSG_D_OP12 0x8D
+#define CEC_RX_MSG_E_OP13 0x8E
+#define CEC_RX_MSG_F_OP14 0x8F
+
+/* read only */
+#define CEC_RX_MSG_LENGTH 0x90
+#define CEC_RX_MSG_STATUS 0x91
+#define CEC_RX_NUM_MSG 0x92
+#define CEC_TX_MSG_STATUS 0x93
+#define CEC_TX_NUM_MSG 0x94
+
+/* tx_msg_cmd definition */
+#define TX_NO_OP 0 /* No transaction */
+#define TX_REQ_CURRENT 1 /* Transmit earliest message in buffer */
+#define TX_ABORT 2 /* Abort transmitting earliest message */
+/* Overwrite earliest message in buffer and transmit next message */
+#define TX_REQ_NEXT 3
+
+/* tx_msg_status definition */
+#define TX_IDLE 0 /* No transaction */
+#define TX_BUSY 1 /* Transmitter is busy */
+/* Message has been successfully transmitted */
+#define TX_DONE 2
+#define TX_ERROR 3 /* Message has been transmitted with error */
+
+/* rx_msg_cmd */
+#define RX_NO_OP 0 /* No transaction */
+#define RX_ACK_CURRENT 1 /* Read earliest message in buffer */
+#define RX_DISABLE 2 /* Disable receiving latest message */
+/* Clear earliest message from buffer and read next message */
+#define RX_ACK_NEXT 3
+
+/* rx_msg_status */
+#define RX_IDLE 0 /* No transaction */
+#define RX_BUSY 1 /* Receiver is busy */
+#define RX_DONE 2 /* Message has been received successfully */
+#define RX_ERROR 3 /* Message has been received with error */
+
+#define TOP_HPD_PWR5V 0x002
+#define TOP_ARCTX_CNTL 0x010
+#define TOP_CLK_CNTL 0x001
+#define TOP_EDID_GEN_CNTL 0x004
+#define TOP_EDID_ADDR_CEC 0x005
+
+/** Register address: audio clock interrupt clear enable */
+#define DWC_AUD_CEC_IEN_CLR (0xF90UL)
+/** Register address: audio clock interrupt set enable */
+#define DWC_AUD_CEC_IEN_SET (0xF94UL)
+/** Register address: audio clock interrupt status */
+#define DWC_AUD_CEC_ISTS (0xF98UL)
+/** Register address: audio clock interrupt enable */
+#define DWC_AUD_CEC_IEN (0xF9CUL)
+/** Register address: audio clock interrupt clear status */
+#define DWC_AUD_CEC_ICLR (0xFA0UL)
+/** Register address: audio clock interrupt set status */
+#define DWC_AUD_CEC_ISET (0xFA4UL)
+/** Register address: DMI disable interface */
+#define DWC_DMI_DISABLE_IF (0xFF4UL)
+
+/*---- registers for EE CEC ----*/
+#define DWC_CEC_CTRL 0x1F00
+#define DWC_CEC_STAT 0x1F04
+#define DWC_CEC_MASK 0x1F08
+#define DWC_CEC_POLARITY 0x1F0C
+#define DWC_CEC_INT 0x1F10
+#define DWC_CEC_ADDR_L 0x1F14
+#define DWC_CEC_ADDR_H 0x1F18
+#define DWC_CEC_TX_CNT 0x1F1C
+#define DWC_CEC_RX_CNT 0x1F20
+#define DWC_CEC_TX_DATA0 0x1F40
+#define DWC_CEC_TX_DATA1 0x1F44
+#define DWC_CEC_TX_DATA2 0x1F48
+#define DWC_CEC_TX_DATA3 0x1F4C
+#define DWC_CEC_TX_DATA4 0x1F50
+#define DWC_CEC_TX_DATA5 0x1F54
+#define DWC_CEC_TX_DATA6 0x1F58
+#define DWC_CEC_TX_DATA7 0x1F5C
+#define DWC_CEC_TX_DATA8 0x1F60
+#define DWC_CEC_TX_DATA9 0x1F64
+#define DWC_CEC_TX_DATA10 0x1F68
+#define DWC_CEC_TX_DATA11 0x1F6C
+#define DWC_CEC_TX_DATA12 0x1F70
+#define DWC_CEC_TX_DATA13 0x1F74
+#define DWC_CEC_TX_DATA14 0x1F78
+#define DWC_CEC_TX_DATA15 0x1F7C
+#define DWC_CEC_RX_DATA0 0x1F80
+#define DWC_CEC_RX_DATA1 0x1F84
+#define DWC_CEC_RX_DATA2 0x1F88
+#define DWC_CEC_RX_DATA3 0x1F8C
+#define DWC_CEC_RX_DATA4 0x1F90
+#define DWC_CEC_RX_DATA5 0x1F94
+#define DWC_CEC_RX_DATA6 0x1F98
+#define DWC_CEC_RX_DATA7 0x1F9C
+#define DWC_CEC_RX_DATA8 0x1FA0
+#define DWC_CEC_RX_DATA9 0x1FA4
+#define DWC_CEC_RX_DATA10 0x1FA8
+#define DWC_CEC_RX_DATA11 0x1FAC
+#define DWC_CEC_RX_DATA12 0x1FB0
+#define DWC_CEC_RX_DATA13 0x1FB4
+#define DWC_CEC_RX_DATA14 0x1FB8
+#define DWC_CEC_RX_DATA15 0x1FBC
+#define DWC_CEC_LOCK 0x1FC0
+#define DWC_CEC_WKUPCTRL 0x1FC4
+
+/* FOR AO_CECB */
+#define AO_CECB_CTRL_ADDR 0x00
+#define AO_CECB_INTR_MASK_ADDR 0x02
+#define AO_CECB_LADD_LOW_ADDR 0x05
+#define AO_CECB_LADD_HIGH_ADDR 0x06
+#define AO_CECB_TX_CNT_ADDR 0x07
+#define AO_CECB_RX_CNT_ADDR 0x08
+#define AO_CECB_TX_DATA00_ADDR 0x10
+#define AO_CECB_TX_DATA01_ADDR 0x11
+#define AO_CECB_TX_DATA02_ADDR 0x12
+#define AO_CECB_TX_DATA03_ADDR 0x13
+#define AO_CECB_TX_DATA04_ADDR 0x14
+#define AO_CECB_TX_DATA05_ADDR 0x15
+#define AO_CECB_TX_DATA06_ADDR 0x16
+#define AO_CECB_TX_DATA07_ADDR 0x17
+#define AO_CECB_TX_DATA08_ADDR 0x18
+#define AO_CECB_TX_DATA09_ADDR 0x19
+#define AO_CECB_TX_DATA10_ADDR 0x1A
+#define AO_CECB_TX_DATA11_ADDR 0x1B
+#define AO_CECB_TX_DATA12_ADDR 0x1C
+#define AO_CECB_TX_DATA13_ADDR 0x1D
+#define AO_CECB_TX_DATA14_ADDR 0x1E
+#define AO_CECB_TX_DATA15_ADDR 0x1F
+#define AO_CECB_RX_DATA00_ADDR 0x20
+#define AO_CECB_RX_DATA01_ADDR 0x21
+#define AO_CECB_RX_DATA02_ADDR 0x22
+#define AO_CECB_RX_DATA03_ADDR 0x23
+#define AO_CECB_RX_DATA04_ADDR 0x24
+#define AO_CECB_RX_DATA05_ADDR 0x25
+#define AO_CECB_RX_DATA06_ADDR 0x26
+#define AO_CECB_RX_DATA07_ADDR 0x27
+#define AO_CECB_RX_DATA08_ADDR 0x28
+#define AO_CECB_RX_DATA09_ADDR 0x29
+#define AO_CECB_RX_DATA10_ADDR 0x2A
+#define AO_CECB_RX_DATA11_ADDR 0x2B
+#define AO_CECB_RX_DATA12_ADDR 0x2C
+#define AO_CECB_RX_DATA13_ADDR 0x2D
+#define AO_CECB_RX_DATA14_ADDR 0x2E
+#define AO_CECB_RX_DATA15_ADDR 0x2F
+#define AO_CECB_LOCK_BUF_ADDR 0x30
+#define AO_CECB_WAKEUPCTRL_ADDR 0x31
+
+/* cec ip irq flags bit discription */
+#define EECEC_IRQ_TX_DONE (1 << 16)
+#define EECEC_IRQ_RX_EOM (1 << 17)
+#define EECEC_IRQ_TX_NACK (1 << 18)
+#define EECEC_IRQ_TX_ARB_LOST (1 << 19)
+#define EECEC_IRQ_TX_ERR_INITIATOR (1 << 20)
+#define EECEC_IRQ_RX_ERR_FOLLOWER (1 << 21)
+#define EECEC_IRQ_RX_WAKEUP (1 << 22)
+#define EE_CEC_IRQ_EN_MASK (0xf << 16)
+
+/* cec irq bit flags for AO_CEC_B */
+#define CECB_IRQ_TX_DONE (1 << 0)
+#define CECB_IRQ_RX_EOM (1 << 1)
+#define CECB_IRQ_TX_NACK (1 << 2)
+#define CECB_IRQ_TX_ARB_LOST (1 << 3)
+#define CECB_IRQ_TX_ERR_INITIATOR (1 << 4)
+#define CECB_IRQ_RX_ERR_FOLLOWER (1 << 5)
+#define CECB_IRQ_RX_WAKEUP (1 << 6)
+#define CECB_IRQ_EN_MASK (0xf << 0)
+
+/* common mask */
+#define CEC_IRQ_TX_DONE (1 << (16 - shift))
+#define CEC_IRQ_RX_EOM (1 << (17 - shift))
+#define CEC_IRQ_TX_NACK (1 << (18 - shift))
+#define CEC_IRQ_TX_ARB_LOST (1 << (19 - shift))
+#define CEC_IRQ_TX_ERR_INITIATOR (1 << (20 - shift))
+#define CEC_IRQ_RX_ERR_FOLLOWER (1 << (21 - shift))
+#define CEC_IRQ_RX_WAKEUP (1 << (22 - shift))
+
+#define EDID_CEC_ID_ADDR 0x00a100a0
+#define EDID_AUTO_CEC_EN 0
+
+#define HHI_32K_CLK_CNTL (0x89 << 2)
+
+#ifdef CONFIG_AMLOGIC_AO_CEC
+unsigned int aocec_rd_reg(unsigned long addr);
+void aocec_wr_reg(unsigned long addr, unsigned long data);
+void cecrx_irq_handle(void);
+void cec_logicaddr_set(int l_add);
+void cec_arbit_bit_time_set(unsigned int bit_set,
+ unsigned int time_set, unsigned int flag);
+void cec_irq_enable(bool enable);
+void aocec_irq_enable(bool enable);
+#endif
+
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
extern unsigned long hdmirx_rd_top(unsigned long addr);
extern void hdmirx_wr_top(unsigned long addr, unsigned long data);
extern uint32_t hdmirx_rd_dwc(uint16_t addr);
@@ -50,7 +403,6 @@ static inline uint32_t hdmirx_rd_dwc(uint16_t addr)
}
static inline void hdmirx_wr_dwc(uint16_t addr, uint32_t data)
{
-
}
#endif
diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h
index 5e5abb1..78e69ca 100644
--- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h
+++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_cec_20.h
@@ -276,8 +276,10 @@ enum cec_version_e {
CEC_VERSION_13,
CEC_VERSION_13A,
CEC_VERSION_14A,
+ CEC_VERSION_20,
};
+
#define INFO_MASK_CEC_VERSION (1<<0)
#define INFO_MASK_VENDOR_ID (1<<1)
#define INFO_MASK_DEVICE_TYPE (1<<2)
@@ -305,11 +307,11 @@ struct cec_node_info_t {
*/
struct cec_global_info_t {
dev_t dev_no;
- unsigned int open_count;
+ atomic_t open_count;
unsigned int hal_ctl; /* message controlled by hal */
unsigned int vendor_id:24;
unsigned int menu_lang;
- unsigned char cec_version;
+ unsigned int cec_version;
unsigned char power_status;
unsigned char log_addr;
unsigned char menu_status;