s5p-cec: Add legacy s5p-cec driver

This driver supports Pulse8 libcec library.

Change-Id: Ic6189187ec930a59ffac024a5c5436270f7e83a6
This commit is contained in:
Mauro (mdrjr) Ribeiro
2017-02-24 11:47:19 +09:00
committed by Brian Kim
parent cbdab82ac8
commit 4feec5ce16
11 changed files with 891 additions and 3 deletions

View File

@@ -67,6 +67,13 @@
samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
};
hdmi_cec: hdmi_cec {
samsung,pins = "gpx3-6";
samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV4>;
};
};
&pinctrl_1 {

View File

@@ -81,6 +81,29 @@
status = "disabled";
};
cec: cec@101B0000 {
compatible = "samsung,exynos5-cec";
reg = <0x101B0000 0x1000>;
interrupts = <0 114 0>;
gpios = <&gpx3 6 0xf>;
pinctrl-names = "hdmi_cec";
pinctrl-0 = <&hdmi_cec>;
clock-names = "hdmicec";
clocks = <&clock CLK_HDMI_CEC>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
status = "okay";
hdmiphy-sys {
reg = <0x10040700 0x4>;
};
};
thermal-zones {
cpu0_thermal: cpu0-thermal {

View File

@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/arm 4.9.12 Kernel Configuration
# Linux/arm 4.9.13 Kernel Configuration
#
CONFIG_ARM=y
CONFIG_ARM_HAS_SG_CHAIN=y
@@ -3238,7 +3238,9 @@ CONFIG_V4L_TEST_DRIVERS=y
CONFIG_VIDEO_VIVID=m
CONFIG_VIDEO_VIVID_MAX_DEVS=64
# CONFIG_VIDEO_VIM2M is not set
# CONFIG_DVB_PLATFORM_DRIVERS is not set
CONFIG_DVB_PLATFORM_DRIVERS=y
# CONFIG_DVB_C8SECTPFE is not set
CONFIG_EXYNOS_HDMI_CEC=y
#
# Supported MMC/SDIO adapters

View File

@@ -375,4 +375,5 @@ menuconfig DVB_PLATFORM_DRIVERS
if DVB_PLATFORM_DRIVERS
source "drivers/media/platform/sti/c8sectpfe/Kconfig"
source "drivers/media/platform/s5p-cec/Kconfig"
endif #DVB_PLATFORM_DRIVERS

View File

@@ -51,7 +51,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FCP) += rcar-fcp.o
obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o
obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/
obj-y += omap/
obj-y += omap/ s5p-cec/
obj-$(CONFIG_VIDEO_AM437X_VPFE) += am437x/

View File

@@ -0,0 +1,6 @@
config EXYNOS_HDMI_CEC
tristate "Samsung HDMI CEC Driver"
help
Say Y here if you want support for the HDMI CEC
interface in S5P Samsung SoC. The driver can be compiled
as module.

View File

@@ -0,0 +1,2 @@
obj-$(CONFIG_EXYNOS_HDMI_CEC) += s5p-hdmi_cec.o
s5p-hdmi_cec-y += hdmi_cec.o hdmi_cec_ctrl.o

View File

@@ -0,0 +1,86 @@
/* linux/drivers/media/video/samsung/tvout/hw_if/hw_if.h
*
* Copyright (c) 2010 Samsung Electronics
* http://www.samsung.com/
*
* Header file for interface of Samsung TVOUT-related hardware
*
* 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.
*/
#ifndef _SAMSUNG_TVOUT_CEC_H_
#define _SAMSUNG_TVOUT_CEC_H_ __FILE__
/*****************************************************************************
* This file includes declarations for external functions of
* Samsung TVOUT-related hardware. So only external functions
* to be used by higher layer must exist in this file.
*
* Higher layer must use only the declarations included in this file.
****************************************************************************/
#define to_tvout_plat(d) (to_platform_device(d)->dev.platform_data)
#define DRV_NAME "s5p-cec"
#ifndef tvout_dbg
#ifdef CONFIG_TV_DEBUG
#define tvout_dbg(fmt, ...) \
pr_emerg("[%s] %s(): " fmt, \
DRV_NAME, __func__, ##__VA_ARGS__)
#else
#define tvout_dbg(fmt, ...)
#endif
#endif
enum s5p_tvout_endian {
TVOUT_LITTLE_ENDIAN = 0,
TVOUT_BIG_ENDIAN = 1
};
enum cec_state {
STATE_RX,
STATE_TX,
STATE_DONE,
STATE_ERROR
};
struct cec_rx_struct {
spinlock_t lock;
wait_queue_head_t waitq;
atomic_t state;
u8 *buffer;
unsigned int size;
};
struct cec_tx_struct {
wait_queue_head_t waitq;
atomic_t state;
};
extern struct cec_rx_struct cec_rx_struct;
extern struct cec_tx_struct cec_tx_struct;
void s5p_cec_set_divider(void);
void s5p_cec_enable_rx(void);
void s5p_cec_mask_rx_interrupts(void);
void s5p_cec_unmask_rx_interrupts(void);
void s5p_cec_mask_tx_interrupts(void);
void s5p_cec_unmask_tx_interrupts(void);
void s5p_cec_reset(void);
void s5p_cec_tx_reset(void);
void s5p_cec_rx_reset(void);
void s5p_cec_threshold(void);
void s5p_cec_set_tx_state(enum cec_state state);
void s5p_cec_set_rx_state(enum cec_state state);
void s5p_cec_copy_packet(char *data, size_t count);
void s5p_cec_set_addr(u32 addr);
u32 s5p_cec_get_status(void);
void s5p_clr_pending_tx(void);
void s5p_clr_pending_rx(void);
void s5p_cec_get_rx_buf(u32 size, u8 *buffer);
int s5p_cec_mem_probe(struct platform_device *pdev);
#endif /* _SAMSUNG_TVOUT_CEC_H_ */

View File

@@ -0,0 +1,421 @@
/* linux/drivers/media/video/samsung/tvout/s5p_cec_ctrl.c
*
* Copyright (c) 2009 Samsung Electronics
* http://www.samsung.com/
*
* cec interface 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/slab.h>
#include <linux/uaccess.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
#include <linux/clk.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include "cec.h"
static const struct of_device_id cec_device_table[] = {
{
.compatible = "samsung,exynos5-cec",
.data = (void *)0,
},
{ /* empty */ }
};
MODULE_DEVICE_TABLE(of, cec_device_table);
MODULE_AUTHOR("SangPil Moon");
MODULE_DESCRIPTION("S5P CEC driver");
MODULE_LICENSE("GPL");
#define CEC_IOC_MAGIC 'c'
#define CEC_IOC_SETLADDR _IOW(CEC_IOC_MAGIC, 0, unsigned int)
#define VERSION "1.0" /* Driver version number */
#define CEC_MINOR 243 /* Major 10, Minor 242, /dev/cec */
#define TVOUT_TIMEOUT (3000)
#define CEC_STATUS_TX_RUNNING (1<<0)
#define CEC_STATUS_TX_TRANSFERRING (1<<1)
#define CEC_STATUS_TX_DONE (1<<2)
#define CEC_STATUS_TX_ERROR (1<<3)
#define CEC_STATUS_TX_BYTES (0xFF<<8)
#define CEC_STATUS_RX_RUNNING (1<<16)
#define CEC_STATUS_RX_RECEIVING (1<<17)
#define CEC_STATUS_RX_DONE (1<<18)
#define CEC_STATUS_RX_ERROR (1<<19)
#define CEC_STATUS_RX_BCAST (1<<20)
#define CEC_STATUS_RX_BYTES (0xFF<<24)
/* CEC Rx buffer size */
#define CEC_RX_BUFF_SIZE 16
/* CEC Tx buffer size */
#define CEC_TX_BUFF_SIZE 16
#define TV_CLK_GET_WITH_ERR_CHECK(clk, pdev, clk_name) \
do { \
clk = clk_get(&pdev->dev, clk_name); \
if (IS_ERR(clk)) { \
tvout_dbg( \
"failed to find clock %s\n", clk_name); \
return -ENOENT; \
} \
} while (0);
static atomic_t hdmi_on = ATOMIC_INIT(0);
static DEFINE_MUTEX(cec_lock);
struct clk *hdmi_cec_clk;
static int s5p_cec_open(struct inode *inode, struct file *file)
{
int ret = 0;
mutex_lock(&cec_lock);
clk_prepare_enable(hdmi_cec_clk);
if (atomic_read(&hdmi_on)) {
tvout_dbg("do not allow multiple open for tvout cec\n");
ret = -EBUSY;
goto err_multi_open;
} else
atomic_inc(&hdmi_on);
s5p_cec_reset();
s5p_cec_set_divider();
s5p_cec_threshold();
s5p_cec_unmask_tx_interrupts();
s5p_cec_set_rx_state(STATE_RX);
s5p_cec_unmask_rx_interrupts();
s5p_cec_enable_rx();
err_multi_open:
mutex_unlock(&cec_lock);
return ret;
}
static int s5p_cec_release(struct inode *inode, struct file *file)
{
atomic_dec(&hdmi_on);
s5p_cec_mask_tx_interrupts();
s5p_cec_mask_rx_interrupts();
clk_disable_unprepare(hdmi_cec_clk);
clk_put(hdmi_cec_clk);
return 0;
}
static ssize_t s5p_cec_read(struct file *file, char __user *buffer,
size_t count, loff_t *ppos)
{
ssize_t retval;
unsigned long spin_flags;
if (wait_event_interruptible_timeout(cec_tx_struct.waitq,
atomic_read(&cec_rx_struct.state) == STATE_DONE,
msecs_to_jiffies(TVOUT_TIMEOUT)) == 0) {
tvout_dbg("error : waiting for interrupt is timeout\n");
return -ERESTARTSYS;
}
spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
if (cec_rx_struct.size > count) {
spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
return -1;
}
if (copy_to_user(buffer, cec_rx_struct.buffer, cec_rx_struct.size)) {
spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
tvout_dbg(" copy_to_user() failed!\n");
return -EFAULT;
}
retval = cec_rx_struct.size;
s5p_cec_set_rx_state(STATE_RX);
spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
return retval;
}
static ssize_t s5p_cec_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
char *data;
/* check data size */
if (count > CEC_TX_BUFF_SIZE || count == 0)
return -1;
data = kmalloc(count, GFP_KERNEL);
if (!data) {
tvout_dbg(" kmalloc() failed!\n");
return -1;
}
if (copy_from_user(data, buffer, count)) {
tvout_dbg(" copy_from_user() failed!\n");
kfree(data);
return -EFAULT;
}
s5p_cec_copy_packet(data, count);
kfree(data);
/* wait for interrupt */
if (wait_event_interruptible_timeout(cec_tx_struct.waitq,
atomic_read(&cec_tx_struct.state) != STATE_TX,
msecs_to_jiffies(TVOUT_TIMEOUT)) == 0) {
tvout_dbg("error : waiting for interrupt is timeout\n");
return -ERESTARTSYS;
}
if (atomic_read(&cec_tx_struct.state) == STATE_ERROR)
return -1;
return count;
}
#if 0
static int s5p_cec_ioctl(struct inode *inode, struct file *file, u32 cmd,
unsigned long arg)
#else
static long s5p_cec_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
#endif
{
u32 laddr;
switch (cmd) {
case CEC_IOC_SETLADDR:
if (get_user(laddr, (u32 __user *) arg))
return -EFAULT;
tvout_dbg("logical address = 0x%02x\n", laddr);
s5p_cec_set_addr(laddr);
break;
default:
return -EINVAL;
}
return 0;
}
static u32 s5p_cec_poll(struct file *file, poll_table *wait)
{
poll_wait(file, &cec_rx_struct.waitq, wait);
if (atomic_read(&cec_rx_struct.state) == STATE_DONE)
return POLLIN | POLLRDNORM;
return 0;
}
static const struct file_operations cec_fops = {
.owner = THIS_MODULE,
.open = s5p_cec_open,
.release = s5p_cec_release,
.read = s5p_cec_read,
.write = s5p_cec_write,
#if 1
.unlocked_ioctl = s5p_cec_ioctl,
#else
.ioctl = s5p_cec_ioctl,
#endif
.poll = s5p_cec_poll,
};
static struct miscdevice cec_misc_device = {
.minor = CEC_MINOR,
.name = "CEC",
.fops = &cec_fops,
};
static irqreturn_t s5p_cec_irq_handler(int irq, void *dev_id)
{
u32 status = 0;
status = s5p_cec_get_status();
if (status & CEC_STATUS_TX_DONE) {
if (status & CEC_STATUS_TX_ERROR) {
tvout_dbg(" CEC_STATUS_TX_ERROR!\n");
s5p_cec_set_tx_state(STATE_ERROR);
} else {
tvout_dbg(" CEC_STATUS_TX_DONE!\n");
s5p_cec_set_tx_state(STATE_DONE);
}
s5p_clr_pending_tx();
wake_up_interruptible(&cec_tx_struct.waitq);
}
if (status & CEC_STATUS_RX_DONE) {
if (status & CEC_STATUS_RX_ERROR) {
tvout_dbg(" CEC_STATUS_RX_ERROR!\n");
s5p_cec_rx_reset();
s5p_cec_enable_rx();
} else {
u32 size;
tvout_dbg(" CEC_STATUS_RX_DONE!\n");
/* copy data from internal buffer */
size = status >> 24;
spin_lock(&cec_rx_struct.lock);
s5p_cec_get_rx_buf(size, cec_rx_struct.buffer);
cec_rx_struct.size = size;
s5p_cec_set_rx_state(STATE_DONE);
spin_unlock(&cec_rx_struct.lock);
s5p_cec_enable_rx();
}
/* clear interrupt pending bit */
s5p_clr_pending_rx();
wake_up_interruptible(&cec_rx_struct.waitq);
}
return IRQ_HANDLED;
}
static int s5p_cec_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct pinctrl *pinctrl;
int gpio;
int ret;
u8 *buffer;
s5p_cec_mem_probe(pdev);
if (misc_register(&cec_misc_device)) {
tvout_dbg(" Couldn't register device 10, %d.\n",
CEC_MINOR);
return -EBUSY;
}
if (of_get_property(dev->of_node, "gpios", NULL) != NULL) {
gpio = of_get_gpio(dev->of_node, 0);
if (gpio < 0) {
tvout_dbg("failed to get gpio cec\n");
return -ENODEV;
}
if (gpio_request(gpio, "hdmi-cec")) {
tvout_dbg("failed to request cec gpio\n");
return -ENODEV;
} else {
gpio_direction_input(gpio);
pinctrl = devm_pinctrl_get_select(dev, "hdmi_cec");
if (IS_ERR(pinctrl))
tvout_dbg("failed to set cec gpio");
tvout_dbg("success request GPIO for hdmi-cec");
}
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
tvout_dbg("failed to get irq resource.\n");
return -ENXIO;
}
ret = devm_request_irq(dev, res->start, s5p_cec_irq_handler,
0x00000020, "hdmi-cec", &pdev->id);
if (ret) {
tvout_dbg("request int interrupt failed.\n");
return ret;
}
init_waitqueue_head(&cec_rx_struct.waitq);
spin_lock_init(&cec_rx_struct.lock);
init_waitqueue_head(&cec_tx_struct.waitq);
buffer = kmalloc(CEC_TX_BUFF_SIZE, GFP_KERNEL);
if (!buffer) {
tvout_dbg(" kmalloc() failed!\n");
misc_deregister(&cec_misc_device);
return -EIO;
}
cec_rx_struct.buffer = buffer;
cec_rx_struct.size = 0;
TV_CLK_GET_WITH_ERR_CHECK(hdmi_cec_clk, pdev, "hdmicec");
tvout_dbg("probe successful\n");
return 0;
}
static int s5p_cec_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver s5p_cec_driver = {
.probe = s5p_cec_probe,
.remove = s5p_cec_remove,
.driver = {
.name = "s5p-tvout-cec",
.of_match_table = cec_device_table,
}
};
static int __init s5p_cec_init(void)
{
int ret;
ret = platform_driver_register(&s5p_cec_driver);
if (ret) {
pr_emerg("Platform Device Register Failed %d\n", ret);
return -1;
}
return 0;
}
static void __exit s5p_cec_exit(void)
{
kfree(cec_rx_struct.buffer);
platform_driver_unregister(&s5p_cec_driver);
}
module_init(s5p_cec_init);
module_exit(s5p_cec_exit);

View File

@@ -0,0 +1,247 @@
/* linux/drivers/media/video/samsung/tvout/hw_if/cec.c
*
* Copyright (c) 2009 Samsung Electronics
* http://www.samsung.com/
*
* 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/io.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <linux/irqreturn.h>
#include <linux/stddef.h>
#include <linux/of_address.h>
#include "regs-cec.h"
#include "cec.h"
#define S5P_HDMI_FIN 24000000
#define CEC_DIV_RATIO 320000
#define CEC_MESSAGE_BROADCAST_MASK 0x0F
#define CEC_MESSAGE_BROADCAST 0x0F
#define CEC_FILTER_THRESHOLD 0x15
void __iomem *cec_base;
void __iomem *pmu_regs;
struct cec_rx_struct cec_rx_struct;
struct cec_tx_struct cec_tx_struct;
void s5p_cec_set_divider(void)
{
u32 div_ratio, reg, div_val;
div_ratio = S5P_HDMI_FIN / CEC_DIV_RATIO - 1;
reg = readl(pmu_regs);
reg = (reg & ~(0x3FF << 16)) | (div_ratio << 16);
writel(reg, pmu_regs);
div_val = CEC_DIV_RATIO * 0.00005 - 1;
writeb(0x0, cec_base + S5P_CES_DIVISOR_3);
writeb(0x0, cec_base + S5P_CES_DIVISOR_2);
writeb(0x0, cec_base + S5P_CES_DIVISOR_1);
writeb(div_val, cec_base + S5P_CES_DIVISOR_0);
}
void s5p_cec_enable_rx(void)
{
u8 reg;
reg = readb(cec_base + S5P_CES_RX_CTRL);
reg |= S5P_CES_RX_CTRL_ENABLE;
writeb(reg, cec_base + S5P_CES_RX_CTRL);
}
void s5p_cec_mask_rx_interrupts(void)
{
u8 reg;
reg = readb(cec_base + S5P_CES_IRQ_MASK);
reg |= S5P_CES_IRQ_RX_DONE;
reg |= S5P_CES_IRQ_RX_ERROR;
writeb(reg, cec_base + S5P_CES_IRQ_MASK);
}
void s5p_cec_unmask_rx_interrupts(void)
{
u8 reg;
reg = readb(cec_base + S5P_CES_IRQ_MASK);
reg &= ~S5P_CES_IRQ_RX_DONE;
reg &= ~S5P_CES_IRQ_RX_ERROR;
writeb(reg, cec_base + S5P_CES_IRQ_MASK);
}
void s5p_cec_mask_tx_interrupts(void)
{
u8 reg;
reg = readb(cec_base + S5P_CES_IRQ_MASK);
reg |= S5P_CES_IRQ_TX_DONE;
reg |= S5P_CES_IRQ_TX_ERROR;
writeb(reg, cec_base + S5P_CES_IRQ_MASK);
}
void s5p_cec_unmask_tx_interrupts(void)
{
u8 reg;
reg = readb(cec_base + S5P_CES_IRQ_MASK);
reg &= ~S5P_CES_IRQ_TX_DONE;
reg &= ~S5P_CES_IRQ_TX_ERROR;
writeb(reg, cec_base + S5P_CES_IRQ_MASK);
}
void s5p_cec_reset(void)
{
u8 reg;
writeb(S5P_CES_RX_CTRL_RESET, cec_base + S5P_CES_RX_CTRL);
writeb(S5P_CES_TX_CTRL_RESET, cec_base + S5P_CES_TX_CTRL);
reg = readb(cec_base + 0xc4);
reg &= ~0x1;
writeb(reg, cec_base + 0xc4);
}
void s5p_cec_tx_reset(void)
{
writeb(S5P_CES_TX_CTRL_RESET, cec_base + S5P_CES_TX_CTRL);
}
void s5p_cec_rx_reset(void)
{
u8 reg;
writeb(S5P_CES_RX_CTRL_RESET, cec_base + S5P_CES_RX_CTRL);
reg = readb(cec_base + 0xc4);
reg &= ~0x1;
writeb(reg, cec_base + 0xc4);
}
void s5p_cec_threshold(void)
{
writeb(CEC_FILTER_THRESHOLD, cec_base + S5P_CES_RX_FILTER_TH);
writeb(0, cec_base + S5P_CES_RX_FILTER_CTRL);
}
void s5p_cec_set_tx_state(enum cec_state state)
{
atomic_set(&cec_tx_struct.state, state);
}
void s5p_cec_set_rx_state(enum cec_state state)
{
atomic_set(&cec_rx_struct.state, state);
}
void s5p_cec_copy_packet(char *data, size_t count)
{
int i = 0;
u8 reg;
while (i < count) {
writeb(data[i], cec_base + (S5P_CES_TX_BUFF0 + (i * 4)));
i++;
}
writeb(count, cec_base + S5P_CES_TX_BYTES);
s5p_cec_set_tx_state(STATE_TX);
reg = readb(cec_base + S5P_CES_TX_CTRL);
reg |= S5P_CES_TX_CTRL_START;
if ((data[0] & CEC_MESSAGE_BROADCAST_MASK) == CEC_MESSAGE_BROADCAST)
reg |= S5P_CES_TX_CTRL_BCAST;
else
reg &= ~S5P_CES_TX_CTRL_BCAST;
reg |= 0x50;
writeb(reg, cec_base + S5P_CES_TX_CTRL);
}
void s5p_cec_set_addr(u32 addr)
{
writeb(addr & 0x0F, cec_base + S5P_CES_LOGIC_ADDR);
}
u32 s5p_cec_get_status(void)
{
u32 status = 0;
status = readb(cec_base + S5P_CES_STATUS_0);
status |= readb(cec_base + S5P_CES_STATUS_1) << 8;
status |= readb(cec_base + S5P_CES_STATUS_2) << 16;
status |= readb(cec_base + S5P_CES_STATUS_3) << 24;
tvout_dbg("status = 0x%x!\n", status);
return status;
}
void s5p_clr_pending_tx(void)
{
writeb(S5P_CES_IRQ_TX_DONE | S5P_CES_IRQ_TX_ERROR,
cec_base + S5P_CES_IRQ_CLEAR);
}
void s5p_clr_pending_rx(void)
{
writeb(S5P_CES_IRQ_RX_DONE | S5P_CES_IRQ_RX_ERROR,
cec_base + S5P_CES_IRQ_CLEAR);
}
void s5p_cec_get_rx_buf(u32 size, u8 *buffer)
{
u32 i = 0;
while (i < size) {
buffer[i] = readb(cec_base + S5P_CES_RX_BUFF0 + (i * 4));
i++;
}
}
int s5p_cec_mem_probe(struct platform_device *pdev)
{
struct device_node *hdmiphy_sys;
struct resource *res;
int ret = 0;
tvout_dbg("%s\n", __func__);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
tvout_dbg(
"failed to get memory region resource for cec\n");
return -ENXIO;
}
cec_base = devm_ioremap_resource(&pdev->dev, res);
if (cec_base == NULL) {
tvout_dbg(
"failed to claim register region for hdmicec\n");
return -ENOENT;
}
hdmiphy_sys = of_get_child_by_name(pdev->dev.of_node, "hdmiphy-sys");
if (!hdmiphy_sys) {
tvout_dbg( "No sys-controller interface for hdmiphy\n");
return -ENODEV;
}
pmu_regs = of_iomap(hdmiphy_sys, 0);
if (pmu_regs == NULL) {
tvout_dbg("Can't get hdmiphy pmu control register\n");
return -ENOMEM;
}
return ret;
}

View File

@@ -0,0 +1,93 @@
/* linux/arch/arm/mach-exynos/include/mach/regs-cec.h
*
* Copyright (c) 2010 Samsung Electronics
* http://www.samsung.com/
*
* CEC register header 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.
*/
#ifndef __ARCH_ARM_REGS_CEC_H
#define __ARCH_ARM_REGS_CEC_H
/*
* Register part
*/
#define S5P_CES_STATUS_0 (0x0000)
#define S5P_CES_STATUS_1 (0x0004)
#define S5P_CES_STATUS_2 (0x0008)
#define S5P_CES_STATUS_3 (0x000C)
#define S5P_CES_IRQ_MASK (0x0010)
#define S5P_CES_IRQ_CLEAR (0x0014)
#define S5P_CES_LOGIC_ADDR (0x0020)
#define S5P_CES_DIVISOR_0 (0x0030)
#define S5P_CES_DIVISOR_1 (0x0034)
#define S5P_CES_DIVISOR_2 (0x0038)
#define S5P_CES_DIVISOR_3 (0x003C)
#define S5P_CES_TX_CTRL (0x0040)
#define S5P_CES_TX_BYTES (0x0044)
#define S5P_CES_TX_STAT0 (0x0060)
#define S5P_CES_TX_STAT1 (0x0064)
#define S5P_CES_TX_BUFF0 (0x0080)
#define S5P_CES_TX_BUFF1 (0x0084)
#define S5P_CES_TX_BUFF2 (0x0088)
#define S5P_CES_TX_BUFF3 (0x008C)
#define S5P_CES_TX_BUFF4 (0x0090)
#define S5P_CES_TX_BUFF5 (0x0094)
#define S5P_CES_TX_BUFF6 (0x0098)
#define S5P_CES_TX_BUFF7 (0x009C)
#define S5P_CES_TX_BUFF8 (0x00A0)
#define S5P_CES_TX_BUFF9 (0x00A4)
#define S5P_CES_TX_BUFF10 (0x00A8)
#define S5P_CES_TX_BUFF11 (0x00AC)
#define S5P_CES_TX_BUFF12 (0x00B0)
#define S5P_CES_TX_BUFF13 (0x00B4)
#define S5P_CES_TX_BUFF14 (0x00B8)
#define S5P_CES_TX_BUFF15 (0x00BC)
#define S5P_CES_RX_CTRL (0x00C0)
#define S5P_CES_RX_STAT0 (0x00E0)
#define S5P_CES_RX_STAT1 (0x00E4)
#define S5P_CES_RX_BUFF0 (0x0100)
#define S5P_CES_RX_BUFF1 (0x0104)
#define S5P_CES_RX_BUFF2 (0x0108)
#define S5P_CES_RX_BUFF3 (0x010C)
#define S5P_CES_RX_BUFF4 (0x0110)
#define S5P_CES_RX_BUFF5 (0x0114)
#define S5P_CES_RX_BUFF6 (0x0118)
#define S5P_CES_RX_BUFF7 (0x011C)
#define S5P_CES_RX_BUFF8 (0x0120)
#define S5P_CES_RX_BUFF9 (0x0124)
#define S5P_CES_RX_BUFF10 (0x0128)
#define S5P_CES_RX_BUFF11 (0x012C)
#define S5P_CES_RX_BUFF12 (0x0130)
#define S5P_CES_RX_BUFF13 (0x0134)
#define S5P_CES_RX_BUFF14 (0x0138)
#define S5P_CES_RX_BUFF15 (0x013C)
#define S5P_CES_RX_FILTER_CTRL (0x0180)
#define S5P_CES_RX_FILTER_TH (0x0184)
/*
* Bit definition part
*/
#define S5P_CES_IRQ_TX_DONE (1<<0)
#define S5P_CES_IRQ_TX_ERROR (1<<1)
#define S5P_CES_IRQ_RX_DONE (1<<4)
#define S5P_CES_IRQ_RX_ERROR (1<<5)
#define S5P_CES_TX_CTRL_START (1<<0)
#define S5P_CES_TX_CTRL_BCAST (1<<1)
#define S5P_CES_TX_CTRL_RETRY (0x04<<4)
#define S5P_CES_TX_CTRL_RESET (1<<7)
#define S5P_CES_RX_CTRL_ENABLE (1<<0)
#define S5P_CES_RX_CTRL_RESET (1<<7)
#define S5P_CES_LOGIC_ADDR_MASK (0xF)
#endif /* __ARCH_ARM_REGS_CEC_H */