From 42225b4a83a64dc3bd8ebaf41150a8d7437c06e1 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 11 Jul 2014 05:25:37 +0200 Subject: [PATCH] linux-cuboxi: update to linux-cuboxi-27bb585 Signed-off-by: Stephan Raue --- packages/linux/package.mk | 2 +- .../linux/linux-999.99.22-hdmi-cec.patch | 731 ------------------ .../linux/linux-999.99.23-hdmi-cec-fix.patch | 76 -- 3 files changed, 1 insertion(+), 808 deletions(-) delete mode 100644 projects/Cuboxi/patches/linux/linux-999.99.22-hdmi-cec.patch delete mode 100644 projects/Cuboxi/patches/linux/linux-999.99.23-hdmi-cec-fix.patch diff --git a/packages/linux/package.mk b/packages/linux/package.mk index efb5c780cd..3648907660 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -19,7 +19,7 @@ PKG_NAME="linux" case "$LINUX" in imx6) - PKG_VERSION="cuboxi-592b2d9" + PKG_VERSION="cuboxi-27bb585" PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" ;; *) diff --git a/projects/Cuboxi/patches/linux/linux-999.99.22-hdmi-cec.patch b/projects/Cuboxi/patches/linux/linux-999.99.22-hdmi-cec.patch deleted file mode 100644 index 3b667f9000..0000000000 --- a/projects/Cuboxi/patches/linux/linux-999.99.22-hdmi-cec.patch +++ /dev/null @@ -1,731 +0,0 @@ -From 74fc2e85c080b0ddc2a4b2565eda97c55300303d Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Sat, 26 Apr 2014 16:50:32 +0200 -Subject: [PATCH] Merge all CEC driver changes to 3.10 This commit pushes all - changes I did in the 3.0.35 kernel to improve/fix its behavior with libcec - port for imx6 - -It also fixes CEC clock handling in case of FB mode change event -and of HDMI cable disconnection ---- - drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 327 +++++++++++++++--------------------- - drivers/video/mxc/mxc_hdmi.c | 14 +- - 2 files changed, 147 insertions(+), 194 deletions(-) - -diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -index d0113ee..3a8aff4 100644 ---- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -+++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -@@ -55,6 +55,8 @@ - #define MESSAGE_TYPE_CONNECTED 4 - #define MESSAGE_TYPE_SEND_SUCCESS 5 - -+#define CEC_TX_INPROGRESS -1 -+#define CEC_TX_AVAIL 0 - - struct hdmi_cec_priv { - int receive_error; -@@ -63,7 +65,9 @@ struct hdmi_cec_priv { - bool cec_state; - u8 last_msg[MAX_MESSAGE_LEN]; - u8 msg_len; -- u8 latest_cec_stat; -+ int tx_answer; -+ u16 latest_cec_stat; -+ u8 link_status; - spinlock_t irq_lock; - struct delayed_work hdmi_cec_work; - struct mutex lock; -@@ -76,6 +80,7 @@ struct hdmi_cec_event { - struct list_head list; - }; - -+ - static LIST_HEAD(head); - - static int hdmi_cec_major; -@@ -84,11 +89,14 @@ static struct hdmi_cec_priv hdmi_cec_data; - static u8 open_count; - - static wait_queue_head_t hdmi_cec_queue; -+static wait_queue_head_t tx_cec_queue; -+ - static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) - { - struct hdmi_cec_priv *hdmi_cec = data; -- u8 cec_stat = 0; -+ u16 cec_stat = 0; - unsigned long flags; -+ u8 phy_stat0; - - spin_lock_irqsave(&hdmi_cec->irq_lock, flags); - -@@ -96,16 +104,24 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) - - cec_stat = hdmi_readb(HDMI_IH_CEC_STAT0); - hdmi_writeb(cec_stat, HDMI_IH_CEC_STAT0); -- -+ phy_stat0 = hdmi_readb(HDMI_PHY_STAT0) & 0x02; -+ if (hdmi_cec->link_status ^ phy_stat0) { -+ /* HPD value changed */ -+ hdmi_cec->link_status = phy_stat0; -+ if (hdmi_cec->link_status) -+ cec_stat |= 0x80; /* Connected */ -+ else -+ cec_stat |= 0x100; /* Disconnected */ -+ } - if ((cec_stat & (HDMI_IH_CEC_STAT0_ERROR_INIT | \ - HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | \ -- HDMI_IH_CEC_STAT0_DONE)) == 0) { -+ HDMI_IH_CEC_STAT0_DONE | 0x180)) == 0) { - spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags); - return IRQ_HANDLED; - } -- - pr_debug("HDMI CEC interrupt received\n"); -- hdmi_cec->latest_cec_stat = cec_stat; -+ /* FIXME : there is a race with latest_cec_stat */ -+ hdmi_cec->latest_cec_stat = cec_stat ; - - schedule_delayed_work(&(hdmi_cec->hdmi_cec_work), msecs_to_jiffies(20)); - -@@ -118,115 +134,70 @@ void mxc_hdmi_cec_handle(u16 cec_stat) - { - u8 val = 0, i = 0; - struct hdmi_cec_event *event = NULL; -- -- /* The current transmission is successful (for initiator only). */ -+ /*The current transmission is successful (for initiator only).*/ - if (!open_count) - return; - - if (cec_stat & HDMI_IH_CEC_STAT0_DONE) { -- -- event = vmalloc(sizeof(struct hdmi_cec_event)); -- if (NULL == event) { -- pr_err("%s: Not enough memory!\n", __func__); -- return; -- } -- -- memset(event, 0, sizeof(struct hdmi_cec_event)); -- event->event_type = MESSAGE_TYPE_SEND_SUCCESS; -- -- mutex_lock(&hdmi_cec_data.lock); -- list_add_tail(&event->list, &head); -- mutex_unlock(&hdmi_cec_data.lock); -- -- wake_up(&hdmi_cec_queue); -+ hdmi_cec_data.tx_answer = cec_stat; -+ wake_up(&tx_cec_queue); - } -- -- /* EOM is detected so that the received data is ready -- * in the receiver data buffer -- */ -+ /*EOM is detected so that the received data is ready in the receiver data buffer*/ - if (cec_stat & HDMI_IH_CEC_STAT0_EOM) { -- - hdmi_writeb(0x02, HDMI_IH_CEC_STAT0); -- - event = vmalloc(sizeof(struct hdmi_cec_event)); - if (NULL == event) { - pr_err("%s: Not enough memory!\n", __func__); - return; - } - memset(event, 0, sizeof(struct hdmi_cec_event)); -- - event->msg_len = hdmi_readb(HDMI_CEC_RX_CNT); - if (!event->msg_len) { - pr_err("%s: Invalid CEC message length!\n", __func__); - return; - } - event->event_type = MESSAGE_TYPE_RECEIVE_SUCCESS; -- - for (i = 0; i < event->msg_len; i++) - event->msg[i] = hdmi_readb(HDMI_CEC_RX_DATA0+i); - hdmi_writeb(0x0, HDMI_CEC_LOCK); -- - mutex_lock(&hdmi_cec_data.lock); - list_add_tail(&event->list, &head); - mutex_unlock(&hdmi_cec_data.lock); -- - wake_up(&hdmi_cec_queue); - } -- -- /* An error is detected on cec line (for initiator only). */ -+ /*An error is detected on cec line (for initiator only). */ - if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) { -- - mutex_lock(&hdmi_cec_data.lock); - hdmi_cec_data.send_error++; -- if (hdmi_cec_data.send_error > 5) { -- pr_err("%s:Re-transmission is attempted more than 5 times!\n", -- __func__); -+ if (hdmi_cec_data.send_error > 2) { -+ pr_err("%s:Re-transmission is attempted more than 2 times!\n", __func__); - hdmi_cec_data.send_error = 0; - mutex_unlock(&hdmi_cec_data.lock); -+ hdmi_cec_data.tx_answer = cec_stat; -+ wake_up(&tx_cec_queue); - return; - } -- -- for (i = 0; i < hdmi_cec_data.msg_len; i++) { -- hdmi_writeb(hdmi_cec_data.last_msg[i], -- HDMI_CEC_TX_DATA0 + i); -- } -+ for (i = 0; i < hdmi_cec_data.msg_len; i++) -+ hdmi_writeb(hdmi_cec_data.last_msg[i], HDMI_CEC_TX_DATA0+i); - hdmi_writeb(hdmi_cec_data.msg_len, HDMI_CEC_TX_CNT); -- - val = hdmi_readb(HDMI_CEC_CTRL); - val |= 0x01; - hdmi_writeb(val, HDMI_CEC_CTRL); - mutex_unlock(&hdmi_cec_data.lock); - } -- -- /* A frame is not acknowledged in a directly addressed message. -- * Or a frame is negatively acknowledged in -- * a broadcast message (for initiator only). -- */ -+ /*A frame is not acknowledged in a directly addressed message. Or a frame is negatively acknowledged in -+ a broadcast message (for initiator only).*/ - if (cec_stat & HDMI_IH_CEC_STAT0_NACK) { -- event = vmalloc(sizeof(struct hdmi_cec_event)); -- if (NULL == event) { -- pr_err("%s: Not enough memory\n", __func__); -- return; -- } -- memset(event, 0, sizeof(struct hdmi_cec_event)); -- event->event_type = MESSAGE_TYPE_NOACK; -- -- mutex_lock(&hdmi_cec_data.lock); -- list_add_tail(&event->list, &head); -- mutex_unlock(&hdmi_cec_data.lock); -- -- wake_up(&hdmi_cec_queue); -+ hdmi_cec_data.tx_answer = cec_stat; -+ wake_up(&tx_cec_queue); - } -- -- /* An error is notified by a follower. -- * Abnormal logic data bit error (for follower). -- */ -+ /*An error is notified by a follower. Abnormal logic data bit error (for follower).*/ - if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_FOLL) { - hdmi_cec_data.receive_error++; - } -- -- /* HDMI cable connected */ -+ /*HDMI cable connected*/ - if (cec_stat & 0x80) { -+ pr_info("HDMI link connected\n"); - event = vmalloc(sizeof(struct hdmi_cec_event)); - if (NULL == event) { - pr_err("%s: Not enough memory\n", __func__); -@@ -234,16 +205,14 @@ void mxc_hdmi_cec_handle(u16 cec_stat) - } - memset(event, 0, sizeof(struct hdmi_cec_event)); - event->event_type = MESSAGE_TYPE_CONNECTED; -- - mutex_lock(&hdmi_cec_data.lock); - list_add_tail(&event->list, &head); - mutex_unlock(&hdmi_cec_data.lock); -- - wake_up(&hdmi_cec_queue); - } -- -- /* HDMI cable disconnected */ -+ /*HDMI cable disconnected*/ - if (cec_stat & 0x100) { -+ pr_info("HDMI link disconnected\n"); - event = vmalloc(sizeof(struct hdmi_cec_event)); - if (NULL == event) { - pr_err("%s: Not enough memory!\n", __func__); -@@ -251,30 +220,24 @@ void mxc_hdmi_cec_handle(u16 cec_stat) - } - memset(event, 0, sizeof(struct hdmi_cec_event)); - event->event_type = MESSAGE_TYPE_DISCONNECTED; -- - mutex_lock(&hdmi_cec_data.lock); - list_add_tail(&event->list, &head); - mutex_unlock(&hdmi_cec_data.lock); -- - wake_up(&hdmi_cec_queue); - } -- - return; - } - EXPORT_SYMBOL(mxc_hdmi_cec_handle); -- - static void mxc_hdmi_cec_worker(struct work_struct *work) - { - u8 val; -- - mxc_hdmi_cec_handle(hdmi_cec_data.latest_cec_stat); -- val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | -- HDMI_IH_CEC_STAT0_ARB_LOST; -+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ARB_LOST; - hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); - } - - /*! -- * @brief open function for vpu file operation -+ * @brief open function for cec file operation - * - * @return 0 on success or negative error code on error - */ -@@ -285,13 +248,11 @@ static int hdmi_cec_open(struct inode *inode, struct file *filp) - mutex_unlock(&hdmi_cec_data.lock); - return -EBUSY; - } -- - open_count = 1; - filp->private_data = (void *)(&hdmi_cec_data); - hdmi_cec_data.Logical_address = 15; - hdmi_cec_data.cec_state = false; - mutex_unlock(&hdmi_cec_data.lock); -- - return 0; - } - -@@ -299,36 +260,40 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) - { - struct hdmi_cec_event *event = NULL; -- - pr_debug("function : %s\n", __func__); -+ - if (!open_count) - return -ENODEV; -- - mutex_lock(&hdmi_cec_data.lock); - if (false == hdmi_cec_data.cec_state) { - mutex_unlock(&hdmi_cec_data.lock); - return -EACCES; - } -- mutex_unlock(&hdmi_cec_data.lock); - -- /* delete from list */ -- mutex_lock(&hdmi_cec_data.lock); - if (list_empty(&head)) { -- mutex_unlock(&hdmi_cec_data.lock); -- return -EACCES; -+ if (file->f_flags & O_NONBLOCK) { -+ mutex_unlock(&hdmi_cec_data.lock); -+ return -EAGAIN; -+ } else { -+ do { -+ mutex_unlock(&hdmi_cec_data.lock); -+ if (wait_event_interruptible(hdmi_cec_queue, (!list_empty(&head)))) -+ return -ERESTARTSYS; -+ mutex_lock(&hdmi_cec_data.lock); -+ } while (list_empty(&head)); -+ } - } -+ - event = list_first_entry(&head, struct hdmi_cec_event, list); - list_del(&event->list); - mutex_unlock(&hdmi_cec_data.lock); -- - if (copy_to_user(buf, event, -- sizeof(struct hdmi_cec_event) - sizeof(struct list_head))) { -+ sizeof(struct hdmi_cec_event) - sizeof(struct list_head))) { - vfree(event); - return -EFAULT; - } - vfree(event); -- -- return sizeof(struct hdmi_cec_event); -+ return (sizeof(struct hdmi_cec_event) - sizeof(struct list_head)); - } - - static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, -@@ -339,58 +304,77 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, - u8 msg_len = 0, val = 0; - - pr_debug("function : %s\n", __func__); -+ - if (!open_count) - return -ENODEV; -- - mutex_lock(&hdmi_cec_data.lock); - if (false == hdmi_cec_data.cec_state) { - mutex_unlock(&hdmi_cec_data.lock); - return -EACCES; - } -+ /* Ensure that there is only one writer who is the only listener of tx_cec_queue */ -+ if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) { -+ mutex_unlock(&hdmi_cec_data.lock); -+ return -EBUSY; -+ } - mutex_unlock(&hdmi_cec_data.lock); -- - if (count > MAX_MESSAGE_LEN) - return -EINVAL; -- -- mutex_lock(&hdmi_cec_data.lock); -- hdmi_cec_data.send_error = 0; - memset(&msg, 0, MAX_MESSAGE_LEN); - ret = copy_from_user(&msg, buf, count); -- if (ret) { -- ret = -EACCES; -- goto end; -- } -- -+ if (ret) -+ return -EACCES; -+ mutex_lock(&hdmi_cec_data.lock); -+ hdmi_cec_data.send_error = 0; -+ hdmi_cec_data.tx_answer = CEC_TX_INPROGRESS; - msg_len = count; - hdmi_writeb(msg_len, HDMI_CEC_TX_CNT); -- for (i = 0; i < msg_len; i++) { -+ for (i = 0; i < msg_len; i++) - hdmi_writeb(msg[i], HDMI_CEC_TX_DATA0+i); -- } -- - val = hdmi_readb(HDMI_CEC_CTRL); - val |= 0x01; - hdmi_writeb(val, HDMI_CEC_CTRL); - memcpy(hdmi_cec_data.last_msg, msg, msg_len); - hdmi_cec_data.msg_len = msg_len; -+ mutex_unlock(&hdmi_cec_data.lock); - -- i = 0; -- val = hdmi_readb(HDMI_CEC_CTRL); -- while ((val & 0x01) == 0x1) { -- msleep(50); -- i++; -- if (i > 3) { -- ret = -EIO; -- goto end; -- } -- val = hdmi_readb(HDMI_CEC_CTRL); -+ ret = wait_event_interruptible_timeout(tx_cec_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ); -+ -+ if (ret < 0) { -+ ret = -ERESTARTSYS; -+ goto tx_out; - } - --end: -- mutex_unlock(&hdmi_cec_data.lock); -+ if (hdmi_cec_data.tx_answer & HDMI_IH_CEC_STAT0_DONE) -+ /* msg correctly sent */ -+ ret = msg_len; -+ else -+ ret = -EIO; - -+ tx_out: -+ hdmi_cec_data.tx_answer = CEC_TX_AVAIL; - return ret; - } - -+ -+static void hdmi_stop_device(void) -+{ -+ u8 val; -+ -+ hdmi_writeb(0x10, HDMI_CEC_CTRL); -+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_ARB_LOST | \ -+ HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; -+ hdmi_writeb(val, HDMI_CEC_MASK); -+ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); -+ hdmi_writeb(0x0, HDMI_CEC_POLARITY); -+ val = hdmi_readb(HDMI_MC_CLKDIS); -+ val |= HDMI_MC_CLKDIS_CECCLK_DISABLE; -+ hdmi_writeb(val, HDMI_MC_CLKDIS); -+ mutex_lock(&hdmi_cec_data.lock); -+ hdmi_cec_data.cec_state = false; -+ mutex_unlock(&hdmi_cec_data.lock); -+} -+ - /*! - * @brief IO ctrl function for vpu file operation - * @param cmd IO ctrl command -@@ -402,93 +386,59 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, - int ret = 0, status = 0; - u8 val = 0, msg = 0; - struct mxc_edid_cfg hdmi_edid_cfg; -- - pr_debug("function : %s\n", __func__); - if (!open_count) - return -ENODEV; -- - switch (cmd) { - case HDMICEC_IOC_SETLOGICALADDRESS: - mutex_lock(&hdmi_cec_data.lock); - if (false == hdmi_cec_data.cec_state) { - mutex_unlock(&hdmi_cec_data.lock); -+ pr_err("Trying to set logical address while not started\n"); - return -EACCES; - } -- - hdmi_cec_data.Logical_address = (u8)arg; -- - if (hdmi_cec_data.Logical_address <= 7) { - val = 1 << hdmi_cec_data.Logical_address; - hdmi_writeb(val, HDMI_CEC_ADDR_L); - hdmi_writeb(0, HDMI_CEC_ADDR_H); -- } else if (hdmi_cec_data.Logical_address > 7 && -- hdmi_cec_data.Logical_address <= 15) { -+ } else if (hdmi_cec_data.Logical_address > 7 && hdmi_cec_data.Logical_address <= 15) { - val = 1 << (hdmi_cec_data.Logical_address - 8); - hdmi_writeb(val, HDMI_CEC_ADDR_H); - hdmi_writeb(0, HDMI_CEC_ADDR_L); -- } else { -+ } else - ret = -EINVAL; -- } -- -- /* Send Polling message with same source -- * and destination address -- */ -+ /*Send Polling message with same source and destination address*/ - if (0 == ret && 15 != hdmi_cec_data.Logical_address) { -- msg = (hdmi_cec_data.Logical_address << 4) | -- hdmi_cec_data.Logical_address; -+ msg = (hdmi_cec_data.Logical_address << 4)|hdmi_cec_data.Logical_address; - hdmi_writeb(1, HDMI_CEC_TX_CNT); - hdmi_writeb(msg, HDMI_CEC_TX_DATA0); -- - val = hdmi_readb(HDMI_CEC_CTRL); - val |= 0x01; - hdmi_writeb(val, HDMI_CEC_CTRL); - } -- - mutex_unlock(&hdmi_cec_data.lock); - break; -- - case HDMICEC_IOC_STARTDEVICE: - val = hdmi_readb(HDMI_MC_CLKDIS); - val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; - hdmi_writeb(val, HDMI_MC_CLKDIS); -- - hdmi_writeb(0x02, HDMI_CEC_CTRL); -- -- val = HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK | -- HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; -+ /* Force read unlock */ -+ hdmi_writeb(0x0, HDMI_CEC_LOCK); -+ val = HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; - hdmi_writeb(val, HDMI_CEC_POLARITY); -- -- val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | -- HDMI_IH_CEC_STAT0_ARB_LOST; -+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ARB_LOST; - hdmi_writeb(val, HDMI_CEC_MASK); - hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); -- -+ hdmi_cec_data.link_status = hdmi_readb(HDMI_PHY_STAT0) & 0x02; - mutex_lock(&hdmi_cec_data.lock); - hdmi_cec_data.cec_state = true; - mutex_unlock(&hdmi_cec_data.lock); - break; -- - case HDMICEC_IOC_STOPDEVICE: -- hdmi_writeb(0x10, HDMI_CEC_CTRL); -- -- val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | -- HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_ARB_LOST | -- HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | -- HDMI_IH_CEC_STAT0_DONE; -- hdmi_writeb(val, HDMI_CEC_MASK); -- hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); -- -- hdmi_writeb(0x0, HDMI_CEC_POLARITY); -- -- val = hdmi_readb(HDMI_MC_CLKDIS); -- val |= HDMI_MC_CLKDIS_CECCLK_DISABLE; -- hdmi_writeb(val, HDMI_MC_CLKDIS); -- -- mutex_lock(&hdmi_cec_data.lock); -- hdmi_cec_data.cec_state = false; -- mutex_unlock(&hdmi_cec_data.lock); -+ hdmi_stop_device(); - break; -- - case HDMICEC_IOC_GETPHYADDRESS: - hdmi_get_edid_cfg(&hdmi_edid_cfg); - status = copy_to_user((void __user *)arg, -@@ -497,29 +447,25 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, - if (status) - ret = -EFAULT; - break; -- - default: - ret = -EINVAL; - break; - } -- -- return ret; -+ return ret; - } - - /*! --* @brief Release function for vpu file operation --* @return 0 on success or negative error code on error --*/ -+ * @brief Release function for vpu file operation -+ * @return 0 on success or negative error code on error -+ */ - static int hdmi_cec_release(struct inode *inode, struct file *filp) - { - mutex_lock(&hdmi_cec_data.lock); -- - if (open_count) { - open_count = 0; - hdmi_cec_data.cec_state = false; - hdmi_cec_data.Logical_address = 15; - } -- - mutex_unlock(&hdmi_cec_data.lock); - - return 0; -@@ -531,20 +477,18 @@ static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait) - - pr_debug("function : %s\n", __func__); - -- if (!open_count) -- return -ENODEV; -- -- if (false == hdmi_cec_data.cec_state) -- return -EACCES; -- - poll_wait(file, &hdmi_cec_queue, wait); - -+ /* Always writable */ -+ mask = (POLLOUT | POLLWRNORM); -+ mutex_lock(&hdmi_cec_data.lock); - if (!list_empty(&head)) -- mask |= (POLLIN | POLLRDNORM); -- -+ mask |= (POLLIN | POLLRDNORM); -+ mutex_unlock(&hdmi_cec_data.lock); - return mask; - } - -+ - const struct file_operations hdmi_cec_fops = { - .owner = THIS_MODULE, - .read = hdmi_cec_read, -@@ -563,20 +507,18 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) - struct pinctrl *pinctrl; - int irq = platform_get_irq(pdev, 0); - -- hdmi_cec_major = register_chrdev(hdmi_cec_major, -- "mxc_hdmi_cec", &hdmi_cec_fops); -+ hdmi_cec_major = register_chrdev(hdmi_cec_major, "mxc_hdmi_cec", &hdmi_cec_fops); - if (hdmi_cec_major < 0) { - dev_err(&pdev->dev, "hdmi_cec: unable to get a major for HDMI CEC\n"); - err = -EBUSY; - goto out; - } -- -+ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (unlikely(res == NULL)) { - dev_err(&pdev->dev, "hdmi_cec:No HDMI irq line provided\n"); - goto err_out_chrdev; - } -- - spin_lock_init(&hdmi_cec_data.irq_lock); - - err = devm_request_irq(&pdev->dev, irq, mxc_hdmi_cec_isr, IRQF_SHARED, -@@ -592,8 +534,8 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) - goto err_out_chrdev; - } - -- temp_class = device_create(hdmi_cec_class, NULL, -- MKDEV(hdmi_cec_major, 0), NULL, "mxc_hdmi_cec"); -+ temp_class = device_create(hdmi_cec_class, NULL, MKDEV(hdmi_cec_major, 0), -+ NULL, "mxc_hdmi_cec"); - if (IS_ERR(temp_class)) { - err = PTR_ERR(temp_class); - goto err_out_class; -@@ -606,15 +548,14 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) - } - - init_waitqueue_head(&hdmi_cec_queue); -+ init_waitqueue_head(&tx_cec_queue); - - INIT_LIST_HEAD(&head); - - mutex_init(&hdmi_cec_data.lock); -- - hdmi_cec_data.Logical_address = 15; -- -+ hdmi_cec_data.tx_answer = CEC_TX_AVAIL; - platform_set_drvdata(pdev, &hdmi_cec_data); -- - INIT_DELAYED_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker); - - dev_info(&pdev->dev, "HDMI CEC initialized\n"); -@@ -631,12 +572,14 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) - - static int hdmi_cec_dev_remove(struct platform_device *pdev) - { -+ if (hdmi_cec_data.cec_state) -+ hdmi_stop_device(); - if (hdmi_cec_major > 0) { - device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0)); - class_destroy(hdmi_cec_class); - unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec"); - hdmi_cec_major = 0; -- } -+} - return 0; - } - -@@ -650,9 +593,9 @@ static struct platform_driver mxc_hdmi_cec_driver = { - .probe = hdmi_cec_dev_probe, - .remove = hdmi_cec_dev_remove, - .driver = { -- .name = "mxc_hdmi_cec", -+ .name = "mxc_hdmi_cec", - .of_match_table = imx_hdmi_cec_match, -- }, -+ }, - }; - - module_platform_driver(mxc_hdmi_cec_driver); -diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c -index 20c6d70..88d62ce 100644 ---- a/drivers/video/mxc/mxc_hdmi.c -+++ b/drivers/video/mxc/mxc_hdmi.c -@@ -1708,8 +1708,12 @@ static void mxc_hdmi_enable_video_path(struct mxc_hdmi *hdmi) - hdmi_writeb(0x16, HDMI_FC_CH1PREAM); - hdmi_writeb(0x21, HDMI_FC_CH2PREAM); - -+ /* Save CEC clock */ -+ clkdis = hdmi_readb(HDMI_MC_CLKDIS) & HDMI_MC_CLKDIS_CECCLK_DISABLE; -+ clkdis |= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; -+ - /* Enable pixel clock and tmds data path */ -- clkdis = 0x7F; -+ clkdis = 0x7F & clkdis; - clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; - hdmi_writeb(clkdis, HDMI_MC_CLKDIS); - -@@ -1990,10 +1994,16 @@ static void mxc_hdmi_power_off(struct mxc_dispdrv_handle *disp) - - static void mxc_hdmi_cable_disconnected(struct mxc_hdmi *hdmi) - { -+ u8 clkdis; -+ - dev_dbg(&hdmi->pdev->dev, "%s\n", __func__); - -+ /* Save CEC clock */ -+ clkdis = hdmi_readb(HDMI_MC_CLKDIS) & HDMI_MC_CLKDIS_CECCLK_DISABLE; -+ clkdis |= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; -+ - /* Disable All HDMI clock */ -- hdmi_writeb(0xff, HDMI_MC_CLKDIS); -+ hdmi_writeb(0xff & clkdis, HDMI_MC_CLKDIS); - - mxc_hdmi_phy_disable(hdmi); - --- -1.9.1 - diff --git a/projects/Cuboxi/patches/linux/linux-999.99.23-hdmi-cec-fix.patch b/projects/Cuboxi/patches/linux/linux-999.99.23-hdmi-cec-fix.patch deleted file mode 100644 index e98c659592..0000000000 --- a/projects/Cuboxi/patches/linux/linux-999.99.23-hdmi-cec-fix.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 76796e32b20dd8f34aadad8fd91672017d143812 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Tue, 29 Apr 2014 01:35:01 +0200 -Subject: [PATCH] Fix a bug that could result in CEC interrupts to be - improperly muted in case the CEC_STAT register was 0, the worker was not - invoked and as a consequence the interrupts were not unmuted Also try to play - better with the interrupt sharing with hmdi_video - ---- - drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 21 +++++++++++---------- - 1 file changed, 11 insertions(+), 10 deletions(-) - -diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -index 3a8aff4..85e259c 100644 ---- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -+++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -@@ -97,6 +97,7 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) - u16 cec_stat = 0; - unsigned long flags; - u8 phy_stat0; -+ irqreturn_t ret = IRQ_HANDLED; - - spin_lock_irqsave(&hdmi_cec->irq_lock, flags); - -@@ -105,6 +106,13 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) - cec_stat = hdmi_readb(HDMI_IH_CEC_STAT0); - hdmi_writeb(cec_stat, HDMI_IH_CEC_STAT0); - phy_stat0 = hdmi_readb(HDMI_PHY_STAT0) & 0x02; -+ -+ if ((cec_stat & (HDMI_IH_CEC_STAT0_ERROR_INIT | \ -+ HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | \ -+ HDMI_IH_CEC_STAT0_DONE)) == 0) { -+ ret = IRQ_NONE; -+ cec_stat = 0; -+ } - if (hdmi_cec->link_status ^ phy_stat0) { - /* HPD value changed */ - hdmi_cec->link_status = phy_stat0; -@@ -113,21 +121,14 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) - else - cec_stat |= 0x100; /* Disconnected */ - } -- if ((cec_stat & (HDMI_IH_CEC_STAT0_ERROR_INIT | \ -- HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | \ -- HDMI_IH_CEC_STAT0_DONE | 0x180)) == 0) { -- spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags); -- return IRQ_HANDLED; -- } - pr_debug("HDMI CEC interrupt received\n"); -- /* FIXME : there is a race with latest_cec_stat */ - hdmi_cec->latest_cec_stat = cec_stat ; - - schedule_delayed_work(&(hdmi_cec->hdmi_cec_work), msecs_to_jiffies(20)); - - spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags); - -- return IRQ_HANDLED; -+ return ret; - } - - void mxc_hdmi_cec_handle(u16 cec_stat) -@@ -479,9 +480,9 @@ static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait) - - poll_wait(file, &hdmi_cec_queue, wait); - -- /* Always writable */ -- mask = (POLLOUT | POLLWRNORM); - mutex_lock(&hdmi_cec_data.lock); -+ if (hdmi_cec_data.tx_answer == CEC_TX_AVAIL) -+ mask = (POLLOUT | POLLWRNORM); - if (!list_empty(&head)) - mask |= (POLLIN | POLLRDNORM); - mutex_unlock(&hdmi_cec_data.lock); --- -1.9.1 -