From 7e492306692444143e349fcbfc7ede94edd2e3d0 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Fri, 3 Aug 2018 09:02:00 +0800 Subject: [PATCH] cec: add port info for mix mode PD#170794: cec: add port info for mix mode 1.add port info for output and input mix mode 2.port number= input number + output number 3.r321 dts add 1 output number for mix mode Change-Id: I17692f5fb4526b4f95474f5ea36c11213034724f Signed-off-by: Yong Qin --- arch/arm64/boot/dts/amlogic/atom.dts | 2 +- .../boot/dts/amlogic/txlx_t962e_r321.dts | 5 +- .../dts/amlogic/txlx_t962e_r321_buildroot.dts | 6 +- drivers/amlogic/cec/hdmi_ao_cec.c | 245 ++++++++---------- drivers/amlogic/cec/hdmi_ao_cec.h | 5 +- .../media/vout/hdmi_tx/hdmi_tx_cec_20.h | 4 - 6 files changed, 115 insertions(+), 152 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/atom.dts b/arch/arm64/boot/dts/amlogic/atom.dts index da0b38832378..128e454481b9 100644 --- a/arch/arm64/boot/dts/amlogic/atom.dts +++ b/arch/arm64/boot/dts/amlogic/atom.dts @@ -968,7 +968,7 @@ vendor_id = <0x000000>; product_desc = "TXLX"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ - port_num = <4>; + port_num = <4>; /*all port number*/ ee_cec; output = <1>; arc_port_mask = <0x8>; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index aead155ab741..f741fd7ca1ab 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -967,9 +967,10 @@ vendor_id = <0x000000>; product_desc = "TXLX"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ - port_num = <4>; + port_num = <4>; /*all port number*/ ee_cec; - output = <1>; + output = <1>; /*output port number*/ + /*arc support port:bit 0-3, according to portmap*/ arc_port_mask = <0x8>; interrupts = <0 205 1 0 199 1>; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index feba0be3b401..b414b552c673 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -1004,9 +1004,11 @@ vendor_id = <0x000000>; product_desc = "TXLX"; /* Max Chars: 16 */ cec_osd_string = "AML_TV"; /* Max Chars: 14 */ - port_num = <3>; + port_num = <4>; /*all port number*/ ee_cec; - arc_port_mask = <0x2>; + output = <1>; /*output port number*/ + /*arc support port:bit 0-3, according to portmap*/ + arc_port_mask = <0x8>; interrupts = <0 205 1 0 199 1>; interrupt-names = "hdmi_aocecb","hdmi_aocec"; diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index d2dced29a01a..5cd1dde3c8ce 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -62,22 +62,12 @@ #include static struct early_suspend aocec_suspend_handler; #endif - #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) @@ -102,7 +92,7 @@ struct cec_wakeup_t { struct ao_cec_dev { unsigned long dev_type; struct device_node *node; - unsigned int port_num; + unsigned int port_num; /*total input hdmi port number*/ unsigned int arc_port; unsigned int output; unsigned int hal_flag; @@ -1049,7 +1039,7 @@ static int check_confilct(void) static bool check_physical_addr_valid(int timeout) { while (timeout > 0) { - if (cec_dev->dev_type == DEV_TYPE_TV) + if (cec_dev->dev_type == CEC_TV_ADDR) break; if (phy_addr_test) break; @@ -1746,34 +1736,13 @@ static irqreturn_t ceca_isr_handler(int irq, void *dev_instance) mod_delayed_work(cec_dev->cec_thread, dwork, 0); return IRQ_HANDLED; } - +/* static void check_wake_up(void) { if (wake_ok == 0) cec_request_active_source(); } - -static void cec_dump_info(void) -{ - CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type); - CEC_ERR("wk_logic_addr:0x%x\n", cec_dev->wakup_data.wk_logic_addr); - CEC_ERR("wk_phy_addr:0x%x\n", cec_dev->wakup_data.wk_phy_addr); - CEC_ERR("wk_port_id:0x%x\n", cec_dev->wakup_data.wk_port_id); - CEC_ERR("wakeup_reason:0x%x\n", cec_dev->wakeup_reason); - CEC_ERR("phy_addr:0x%x\n", cec_dev->phy_addr); - CEC_ERR("cec_version:0x%x\n", cec_dev->cec_info.cec_version); - CEC_ERR("hal_ctl:0x%x\n", cec_dev->cec_info.hal_ctl); - CEC_ERR("menu_lang:0x%x\n", cec_dev->cec_info.menu_lang); - CEC_ERR("menu_status:0x%x\n", cec_dev->cec_info.menu_status); - CEC_ERR("open_count:%d\n", cec_dev->cec_info.open_count.counter); - CEC_ERR("vendor_id:0x%x\n", cec_dev->v_data.vendor_id); - CEC_ERR("port_num:0x%x\n", cec_dev->port_num); - CEC_ERR("hal_flag:0x%x\n", cec_dev->hal_flag); - CEC_ERR("hpd_state:0x%x\n", cec_dev->tx_dev->hpd_state); - CEC_ERR("cec_config:0x%x\n", cec_config(0, 0)); - dump_reg(); -} - +*/ /******************** cec class interface *************************/ static ssize_t device_type_show(struct class *cla, struct class_attribute *attr, char *buf) @@ -1932,7 +1901,7 @@ static ssize_t port_status_show(struct class *cla, unsigned int tx_hpd; tx_hpd = cec_dev->tx_dev->hpd_state; - if (cec_dev->dev_type == DEV_TYPE_PLAYBACK) { + if (cec_dev->dev_type != CEC_TV_ADDR) { tmp = tx_hpd; return sprintf(buf, "%x\n", tmp); } @@ -1951,7 +1920,7 @@ static ssize_t pin_status_show(struct class *cla, char p; tx_hpd = cec_dev->tx_dev->hpd_state; - if (cec_dev->dev_type == DEV_TYPE_PLAYBACK) { + if (cec_dev->dev_type != CEC_TV_ADDR) { if (!tx_hpd) { pin_status = 0; return sprintf(buf, "%s\n", "disconnected"); @@ -2160,6 +2129,8 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr, CEC_ERR("wb cecb reg:0x%x val:0x%x\n", addr, val); hdmirx_cec_write(addr, val); } else if (token && strncmp(token, "dump", 4) == 0) { + dump_reg(); + } else if (token && strncmp(token, "status", 6) == 0) { cec_dump_info(); } else if (token && strncmp(token, "rao", 3) == 0) { token = strsep(&cur, delim); @@ -2294,9 +2265,10 @@ static void init_cec_port_info(struct hdmi_port_info *port, /* physical address for TV or repeator */ tx_dev = cec_dev->tx_dev; - if (tx_dev == NULL || cec_dev->dev_type == DEV_TYPE_TV) { + if (tx_dev == NULL || cec_dev->dev_type == CEC_TV_ADDR) { phy_addr = 0; } else if (tx_dev->hdmi_info.vsdb_phy_addr.valid == 1) { + /* get phy address from tx module */ 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; @@ -2313,23 +2285,27 @@ static void init_cec_port_info(struct hdmi_port_info *port, } else break; } - b = cec_dev->port_num; - CEC_ERR("%s phy_addr:%x, port num:%x\n", __func__, phy_addr, b); + CEC_ERR("%s phy_addr:%x, port num:%x\n", __func__, phy_addr, + cec_dev->port_num); + CEC_ERR("port_seq=0x%x\n", cec_dev->port_seq); /* init for port info */ 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; - if (c == 0xf) { /* not used */ + if (c == 0xf) { /* not used */ CEC_INFO("port %d is not used\n", a); continue; } port[e].physical_address = (c) * phy_app + phy_addr; - } else + } else { /* asending order if port_seq is not set */ port[e].physical_address = (a + 1) * phy_app + phy_addr; - if ((e + cec_dev->output) == b) { + } + + /* select input / output port*/ + if ((e + cec_dev->output) == cec_dev->port_num) { port[e].physical_address = phy_addr; port[e].port_id = 0; port[e].type = HDMI_OUTPUT; @@ -2343,56 +2319,75 @@ static void init_cec_port_info(struct hdmi_port_info *port, port[e].arc_supported = 1; else port[e].arc_supported = 0; - CEC_ERR("%s port:%d arc:%d phy:%x,type:%d\n", __func__, + CEC_ERR("portinfo id:%d arc:%d phy:%x,type:%d\n", port[e].port_id, port[e].arc_supported, port[e].physical_address, port[e].type); e++; - if (e >= b) + if (e >= cec_dev->port_num) break; } } + +void cec_dump_info(void) +{ + struct hdmi_port_info *port; + + CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type); + CEC_ERR("wk_logic_addr:0x%x\n", cec_dev->wakup_data.wk_logic_addr); + CEC_ERR("wk_phy_addr:0x%x\n", cec_dev->wakup_data.wk_phy_addr); + CEC_ERR("wk_port_id:0x%x\n", cec_dev->wakup_data.wk_port_id); + CEC_ERR("wakeup_reason:0x%x\n", cec_dev->wakeup_reason); + CEC_ERR("phy_addr:0x%x\n", cec_dev->phy_addr); + CEC_ERR("cec_version:0x%x\n", cec_dev->cec_info.cec_version); + CEC_ERR("hal_ctl:0x%x\n", cec_dev->cec_info.hal_ctl); + CEC_ERR("menu_lang:0x%x\n", cec_dev->cec_info.menu_lang); + CEC_ERR("menu_status:0x%x\n", cec_dev->cec_info.menu_status); + CEC_ERR("open_count:%d\n", cec_dev->cec_info.open_count.counter); + CEC_ERR("vendor_id:0x%x\n", cec_dev->v_data.vendor_id); + CEC_ERR("port_num:0x%x\n", cec_dev->port_num); + CEC_ERR("output:0x%x\n", cec_dev->output); + CEC_ERR("arc_port:0x%x\n", cec_dev->arc_port); + CEC_ERR("hal_flag:0x%x\n", cec_dev->hal_flag); + CEC_ERR("hpd_state:0x%x\n", cec_dev->tx_dev->hpd_state); + CEC_ERR("cec_config:0x%x\n", cec_config(0, 0)); + + port = kcalloc(cec_dev->port_num, sizeof(*port), GFP_KERNEL); + if (port) { + init_cec_port_info(port, cec_dev); + kfree(port); + } +} + static long hdmitx_cec_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; - unsigned long tmp; + unsigned int tmp; struct hdmi_port_info *port; unsigned int a, b, c, d; struct hdmitx_dev *tx_dev; - unsigned int tx_hpd; + /*unsigned 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 && !phy_addr_test) { - /* physical address for mbox */ - if (cec_dev->tx_dev->hdmi_info.vsdb_phy_addr.valid - == 0) { - mutex_unlock(&cec_dev->cec_ioctl_mutex); - return -EINVAL; - } - 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 { - /* physical address for TV or repeator */ - tx_dev = cec_dev->tx_dev; - if (!tx_dev || cec_dev->dev_type == DEV_TYPE_TV) { - tmp = 0; - } 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; - } + /* physical address for TV or repeator */ + tx_dev = cec_dev->tx_dev; + if (!tx_dev || cec_dev->dev_type == CEC_TV_ADDR) { + tmp = 0; + } else if (tx_dev->hdmi_info.vsdb_phy_addr.valid == 1) { + /*hpd attach and wait read edid*/ + 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 (!phy_addr_test) { cec_dev->phy_addr = tmp; cec_phyaddr_config(tmp, 1); @@ -2436,36 +2431,12 @@ static long hdmitx_cec_ioctl(struct file *f, 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 */ - 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 = 0; - port->cec_supported = 1; - /* not support arc for tx */ - port->arc_supported = 0; - 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 { - b = cec_dev->port_num; - init_cec_port_info(port, cec_dev); - if (copy_to_user(argp, port, sizeof(*port) * b)) { - kfree(port); - mutex_unlock(&cec_dev->cec_ioctl_mutex); - return -EINVAL; - } - } + check_physical_addr_valid(20); /*delay time:20 x 100ms*/ + init_cec_port_info(port, cec_dev); + if (copy_to_user(argp, port, sizeof(*port) * + cec_dev->port_num)) + CEC_ERR("err get port info\n"); + kfree(port); break; @@ -2513,24 +2484,23 @@ static long hdmitx_cec_ioctl(struct file *f, break; case CEC_IOC_GET_CONNECT_STATUS: - tx_hpd = cec_dev->tx_dev->hpd_state; - if (cec_dev->dev_type == DEV_TYPE_PLAYBACK) - tmp = tx_hpd; - else { - if (copy_from_user(&a, argp, _IOC_SIZE(cmd))) { - mutex_unlock(&cec_dev->cec_ioctl_mutex); - return -EINVAL; - } - /* mixed for rx & tx */ - if (a != 0) { - tmp = hdmirx_get_connect_info(); - if (tmp & (1 << (a - 1))) - tmp = 1; - else - tmp = 0; - } else - tmp = tx_hpd; + if (copy_from_user(&a, argp, _IOC_SIZE(cmd))) { + mutex_unlock(&cec_dev->cec_ioctl_mutex); + return -EINVAL; } + + /* mixed for rx & tx */ + /* a is current port idx, 0: tx device */ + if (a != 0) { + tmp = hdmirx_get_connect_info(); + if (tmp & (1 << (a - 1))) + tmp = 1; + else + tmp = 0; + } else { + tmp = cec_dev->tx_dev->hpd_state; + } + /*CEC_ERR("port id:%d, sts:%d\n", a, tmp);*/ if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd))) { mutex_unlock(&cec_dev->cec_ioctl_mutex); return -EINVAL; @@ -2547,11 +2517,6 @@ static long hdmitx_cec_ioctl(struct file *f, cec_dev->cec_info.vendor_id = cec_dev->v_data.vendor_id; strncpy(cec_dev->cec_info.osd_name, cec_dev->v_data.cec_osd_string, 14); - - 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: @@ -2559,10 +2524,6 @@ static long hdmitx_cec_ioctl(struct file *f, break; case CEC_IOC_SET_DEV_TYPE: - if (arg > DEV_TYPE_VIDEO_PROCESSOR) { - mutex_unlock(&cec_dev->cec_ioctl_mutex); - return -EINVAL; - } cec_dev->dev_type = arg; break; @@ -2716,17 +2677,19 @@ static int aml_cec_probe(struct platform_device *pdev) cec_dev = devm_kzalloc(&pdev->dev, sizeof(struct ao_cec_dev), GFP_KERNEL); if (IS_ERR(cec_dev)) { - CEC_ERR("device malloc err!\n"); + dev_err(&pdev->dev, "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; + + /*will replace by CEC_IOC_SET_DEV_TYPE*/ + cec_dev->dev_type = CEC_PLAYBACK_DEVICE_1_ADDR; cec_dev->dbg_dev = &pdev->dev; cec_dev->tx_dev = get_hdmitx_device(); cec_dev->cpu_type = get_cpu_type(); cec_dev->node = pdev->dev.of_node; phy_addr_test = 0; + CEC_ERR("cec driver date:%s\n", CEC_DRIVER_VERSION); cec_dbg_init(); /* cdev registe */ r = class_register(&aocec_class); @@ -2884,7 +2847,7 @@ static int aml_cec_probe(struct platform_device *pdev) } cec_dev->hhi_reg = (void *)base; } else - CEC_ERR("no hhi regs\n") + CEC_ERR("no hhi regs\n"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "periphs"); if (res) { base = devm_ioremap(&pdev->dev, res->start, @@ -2997,20 +2960,20 @@ static int aml_cec_probe(struct platform_device *pdev) return 0; tag_cec_msg_alloc_err: - free_irq(cec_dev->irq_cec, (void *)cec_dev); + free_irq(cec_dev->irq_cec, (void *)cec_dev); tag_cec_reg_map_err: - input_free_device(cec_dev->cec_info.remote_cec_dev); + input_free_device(cec_dev->cec_info.remote_cec_dev); tag_cec_alloc_input_err: - destroy_workqueue(cec_dev->cec_thread); + destroy_workqueue(cec_dev->cec_thread); tag_cec_threat_err: - device_destroy(&aocec_class, - MKDEV(cec_dev->cec_info.dev_no, 0)); + device_destroy(&aocec_class, + MKDEV(cec_dev->cec_info.dev_no, 0)); tag_cec_device_create_err: - unregister_chrdev(cec_dev->cec_info.dev_no, CEC_DEV_NAME); + unregister_chrdev(cec_dev->cec_info.dev_no, CEC_DEV_NAME); tag_cec_chr_reg_err: - class_unregister(&aocec_class); + class_unregister(&aocec_class); tag_cec_class_reg: - devm_kfree(&pdev->dev, cec_dev); + devm_kfree(&pdev->dev, cec_dev); tag_cec_devm_err: return ret; } diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 2aea31b968c1..9d19aafb2430 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -18,7 +18,7 @@ #ifndef __AO_CEC_H__ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "Ver 2018/08/07\n" +#define CEC_DRIVER_VERSION "Ver 2018/08/08\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "cec" @@ -40,7 +40,7 @@ #define CEC_FUNC_CFG_ALL 0x2f #define CEC_FUNC_CFG_NONE 0x0 -#define AO_BASE 0xc8100000 +/*#define AO_BASE 0xc8100000*/ #define AO_GPIO_I ((0x0A << 2)) #define PREG_PAD_GPIO3_I (0x01b << 2) @@ -440,5 +440,6 @@ void cec_irq_enable(bool enable); void aocec_irq_enable(bool enable); extern void dump_reg(void); #endif +extern void cec_dump_info(void); #endif /* __AO_CEC_H__ */ 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 9fe74a2d8d06..6f30e0b5bc69 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 @@ -300,10 +300,6 @@ enum cec_version_e { #define ONE_TOUCH_STANDBY_MASK 2 #define AUTO_POWER_ON_MASK 3 - -struct cec_node_info_t { -}; - /* * only for 1 tx device */