Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Unified Diff: drivers/media/video/samsung/tv20/cec_s5pv210.c

Issue 2036011: V4L/DVB : Add S5PV210 TV out driver support (Closed) Base URL: swsolcc@12.23.106.100:kernel-samsung.git
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « drivers/media/video/samsung/tv20/cec_s5pv210.h ('k') | drivers/media/video/samsung/tv20/ddc.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: drivers/media/video/samsung/tv20/cec_s5pv210.c
diff --git a/drivers/media/video/samsung/tv20/cec_s5pv210.c b/drivers/media/video/samsung/tv20/cec_s5pv210.c
new file mode 100644
index 0000000000000000000000000000000000000000..c5b6455b8accfc7a0810ad4bad247d36c6206517
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/cec_s5pv210.c
@@ -0,0 +1,279 @@
+/* linux/drivers/media/video/samsung/tv20/cec_s5pv210.c
+*
+* Copyright (c) 2010 Samsung Electronics Co., Ltd.
+* http://www.samsung.com/
+*
+* S5PV210 - cec ftn file for Samsung TVOut driver
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-cec.h>
+#include "cec.h"
+
+#ifdef CECDEBUG
+#define CECPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[CEC] %s: " fmt, __func__ , ## args)
+#else
+#define CECPRINTK(fmt, args...)
+#endif
+
+static struct resource *cec_mem;
+void __iomem *cec_base;
+
+#define S5P_HDMI_FIN 24000000
+#define CEC_DIV_RATIO 187500
+
+void tv_cec_set_divider(void)
+{
+ u32 div_ratio, reg, div_val;
+
+ div_ratio = S5P_HDMI_FIN/CEC_DIV_RATIO - 1;
+
+ reg = readl(S5P_HDMI_PHY_CONTROL);
+ reg = (reg & ~(0x3FF<<16)) | (div_ratio << 16);
+
+ writel(reg, S5P_HDMI_PHY_CONTROL);
+
+ div_val = CEC_DIV_RATIO * 0.00005 - 1;
+
+ writeb(0x0, cec_base + CEC_DIVISOR_3);
+ writeb(0x0, cec_base + CEC_DIVISOR_2);
+ writeb(0x0, cec_base + CEC_DIVISOR_1);
+ writeb(div_val, cec_base + CEC_DIVISOR_0);
+
+ CECPRINTK("CEC_DIVISOR_3 = 0x%08x\n", readb(cec_base + CEC_DIVISOR_3));
+ CECPRINTK("CEC_DIVISOR_2 = 0x%08x\n", readb(cec_base + CEC_DIVISOR_2));
+ CECPRINTK("CEC_DIVISOR_1 = 0x%08x\n", readb(cec_base + CEC_DIVISOR_1));
+ CECPRINTK("CEC_DIVISOR_0 = 0x%08x\n", readb(cec_base + CEC_DIVISOR_0));
+}
+
+void tv_cec_enable_rx(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_RX_CTRL);
+ reg |= CEC_RX_CTRL_ENABLE;
+ writeb(reg, cec_base + CEC_RX_CTRL);
+
+ CECPRINTK("CEC_RX_CTRL = 0x%08x \n", readb(cec_base + CEC_RX_CTRL));
+}
+
+void tv_cec_mask_rx_interrupts(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_IRQ_MASK);
+ reg |= CEC_IRQ_RX_DONE;
+ reg |= CEC_IRQ_RX_ERROR;
+ writeb(reg, cec_base + CEC_IRQ_MASK);
+
+ CECPRINTK("CEC_IRQ_MASK = 0x%08x \n", readb(cec_base + CEC_IRQ_MASK));
+}
+
+void tv_cec_unmask_rx_interrupts(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_IRQ_MASK);
+ reg &= ~CEC_IRQ_RX_DONE;
+ reg &= ~CEC_IRQ_RX_ERROR;
+ writeb(reg, cec_base + CEC_IRQ_MASK);
+
+ CECPRINTK("CEC_IRQ_MASK = 0x%08x \n", readb(cec_base + CEC_IRQ_MASK));
+}
+
+void tv_cec_mask_tx_interrupts(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_IRQ_MASK);
+ reg |= CEC_IRQ_TX_DONE;
+ reg |= CEC_IRQ_TX_ERROR;
+ writeb(reg, cec_base + CEC_IRQ_MASK);
+
+ CECPRINTK("CEC_IRQ_MASK = 0x%08x \n", readb(cec_base + CEC_IRQ_MASK));
+
+}
+
+void tv_cec_unmask_tx_interrupts(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_IRQ_MASK);
+ reg &= ~CEC_IRQ_TX_DONE;
+ reg &= ~CEC_IRQ_TX_ERROR;
+ writeb(reg, cec_base + CEC_IRQ_MASK);
+
+ CECPRINTK("CEC_IRQ_MASK = 0x%08x \n", readb(cec_base + CEC_IRQ_MASK));
+}
+
+void tv_cec_reset(void)
+{
+ writeb(CEC_RX_CTRL_RESET, cec_base + CEC_RX_CTRL); /* reset CEC Rx */
+ writeb(CEC_TX_CTRL_RESET, cec_base + CEC_TX_CTRL); /* reset CEC Tx */
+
+ CECPRINTK("CEC_RX_CTRL = 0x%08x \n", readb(cec_base + CEC_RX_CTRL));
+ CECPRINTK("CEC_TX_CTRL = 0x%08x \n", readb(cec_base + CEC_TX_CTRL));
+}
+
+void tv_cec_tx_reset(void)
+{
+ writeb(CEC_TX_CTRL_RESET, cec_base + CEC_TX_CTRL); /* reset CEC Tx */
+
+ CECPRINTK("CEC_TX_CTRL = 0x%08x \n", readb(cec_base + CEC_TX_CTRL));
+}
+
+void tv_cec_rx_reset(void)
+{
+ writeb(CEC_RX_CTRL_RESET, cec_base + CEC_RX_CTRL); /* reset CEC Rx */
+ CECPRINTK("CEC_RX_CTRL = 0x%08x \n", readb(cec_base + CEC_RX_CTRL));
+}
+
+void tv_cec_threshold(void)
+{
+ writeb(CEC_FILTER_THRESHOLD, cec_base + CEC_RX_FILTER_TH);
+ /* setup filter */
+ writeb(0, cec_base + CEC_RX_FILTER_CTRL);
+ CECPRINTK("CEC_RX_FILTER_TH = 0x%08x \n",
+ readb(cec_base + CEC_RX_FILTER_TH));
+}
+
+void tv_cec_copy_packet(char *data, size_t count)
+{
+ int i = 0;
+ u8 reg;
+ /* copy packet to hardware buffer */
+ while (i < count) {
+ writeb(data[i], cec_base + (CEC_TX_BUFF0 + (i*4)));
+ i++;
+ }
+
+ /* set number of bytes to transfer */
+ writeb(count, cec_base + CEC_TX_BYTES);
+
+ tv_cec_set_tx_state(STATE_TX);
+
+ /* start transfer */
+ reg = readb(cec_base + CEC_TX_CTRL);
+
+ reg |= CEC_TX_CTRL_START;
+
+ /* if message is broadcast message - set corresponding bit */
+ if ((data[0] & CEC_MESSAGE_BROADCAST_MASK) == CEC_MESSAGE_BROADCAST)
+ reg |= CEC_TX_CTRL_BCAST;
+ else
+ reg &= ~CEC_TX_CTRL_BCAST;
+
+ /* set number of retransmissions */
+ reg |= 0x50;
+
+ writeb(reg, cec_base + CEC_TX_CTRL);
+}
+
+void tv_cec_set_addr(u32 addr)
+{
+ writeb(addr & 0x0F, cec_base + CEC_LOGIC_ADDR);
+
+}
+
+u32 tv_cec_get_status(void)
+{
+ u32 status = 0;
+
+ status = readb(cec_base + CEC_STATUS_0);
+ status |= readb(cec_base + CEC_STATUS_1) << 8;
+ status |= readb(cec_base + CEC_STATUS_2) << 16;
+ status |= readb(cec_base + CEC_STATUS_3) << 24;
+
+ CECPRINTK("status = 0x%x!\n", status);
+
+ return status;
+}
+
+void tv_clr_pending_tx(void)
+{
+ /* clear interrupt pending bit */
+ writeb(CEC_IRQ_TX_DONE | CEC_IRQ_TX_ERROR, cec_base + CEC_IRQ_CLEAR);
+}
+
+void tv_clr_pending_rx(void)
+{
+ /* clear interrupt pending bit */
+ writeb(CEC_IRQ_RX_DONE | CEC_IRQ_RX_ERROR, cec_base + CEC_IRQ_CLEAR);
+}
+
+void tv_cec_get_rx_buf(u32 size, u8 *buffer)
+{
+ u32 i = 0;
+
+ while (i < size) {
+ buffer[i] = readb(cec_base + CEC_RX_BUFF0 + (i * 4));
+ i++;
+ }
+}
+
+void __init tv_cec_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ size_t size;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource for cec\n");
+ goto cec_err;
+
+ }
+
+ size = (res->end - res->start) + 1;
+
+ cec_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (cec_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region for cec\n");
+ goto cec_err;
+
+ }
+
+ cec_base = ioremap(res->start, size);
+
+ if (cec_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region for cec\n");
+ goto cec_err;
+
+
+ }
+
+ return;
+
+cec_err:
+ dev_err(&pdev->dev,
+ "failed to cec_probe()\n");
+
+}
+
+int __init tv_cec_release(struct platform_device *pdev)
+{
+ iounmap(cec_base);
+
+ /* remove memory region */
+ if (cec_mem != NULL) {
+ if (release_resource(cec_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(cec_mem);
+
+ cec_mem = NULL;
+ }
+
+ return 0;
+}
« no previous file with comments | « drivers/media/video/samsung/tv20/cec_s5pv210.h ('k') | drivers/media/video/samsung/tv20/ddc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698