Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CEC_SAMSUNG_S5P) += s5p-cec.o
s5p-cec-y += s5p_cec.o exynos_hdmi_cecctrl.o
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* drivers/media/platform/s5p-cec/exynos_hdmi_cec.h
*
* Copyright (c) 2010, 2014 Samsung Electronics
* http://www.samsung.com/
*
* Header file for interface of Samsung Exynos hdmi cec hardware
*/
#ifndef _EXYNOS_HDMI_CEC_H_
#define _EXYNOS_HDMI_CEC_H_ __FILE__
#include <linux/regmap.h>
#include "s5p_cec.h"
void s5p_cec_set_divider(struct s5p_cec_dev *cec);
void s5p_cec_enable_rx(struct s5p_cec_dev *cec);
void s5p_cec_mask_rx_interrupts(struct s5p_cec_dev *cec);
void s5p_cec_unmask_rx_interrupts(struct s5p_cec_dev *cec);
void s5p_cec_mask_tx_interrupts(struct s5p_cec_dev *cec);
void s5p_cec_unmask_tx_interrupts(struct s5p_cec_dev *cec);
void s5p_cec_reset(struct s5p_cec_dev *cec);
void s5p_cec_tx_reset(struct s5p_cec_dev *cec);
void s5p_cec_rx_reset(struct s5p_cec_dev *cec);
void s5p_cec_threshold(struct s5p_cec_dev *cec);
void s5p_cec_copy_packet(struct s5p_cec_dev *cec, char *data,
size_t count, u8 retries);
void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr);
u32 s5p_cec_get_status(struct s5p_cec_dev *cec);
void s5p_clr_pending_tx(struct s5p_cec_dev *cec);
void s5p_clr_pending_rx(struct s5p_cec_dev *cec);
void s5p_cec_get_rx_buf(struct s5p_cec_dev *cec, u32 size, u8 *buffer);
#endif /* _EXYNOS_HDMI_CEC_H_ */
@@ -0,0 +1,206 @@
// SPDX-License-Identifier: GPL-2.0-only
/* drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c
*
* Copyright (c) 2009, 2014 Samsung Electronics
* http://www.samsung.com/
*
* cec ftn file for Samsung TVOUT driver
*/
#include <linux/io.h>
#include <linux/device.h>
#include "exynos_hdmi_cec.h"
#include "regs-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 s5p_cec_set_divider(struct s5p_cec_dev *cec)
{
u32 div_ratio, div_val;
unsigned int reg;
div_ratio = S5P_HDMI_FIN / CEC_DIV_RATIO - 1;
if (regmap_read(cec->pmu, EXYNOS_HDMI_PHY_CONTROL, &reg)) {
dev_err(cec->dev, "failed to read phy control\n");
return;
}
reg = (reg & ~(0x3FF << 16)) | (div_ratio << 16);
if (regmap_write(cec->pmu, EXYNOS_HDMI_PHY_CONTROL, reg)) {
dev_err(cec->dev, "failed to write phy control\n");
return;
}
div_val = CEC_DIV_RATIO * 0.00005 - 1;
writeb(0x0, cec->reg + S5P_CEC_DIVISOR_3);
writeb(0x0, cec->reg + S5P_CEC_DIVISOR_2);
writeb(0x0, cec->reg + S5P_CEC_DIVISOR_1);
writeb(div_val, cec->reg + S5P_CEC_DIVISOR_0);
}
void s5p_cec_enable_rx(struct s5p_cec_dev *cec)
{
u8 reg;
reg = readb(cec->reg + S5P_CEC_RX_CTRL);
reg |= S5P_CEC_RX_CTRL_ENABLE;
writeb(reg, cec->reg + S5P_CEC_RX_CTRL);
}
void s5p_cec_mask_rx_interrupts(struct s5p_cec_dev *cec)
{
u8 reg;
reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
reg |= S5P_CEC_IRQ_RX_DONE;
reg |= S5P_CEC_IRQ_RX_ERROR;
writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
}
void s5p_cec_unmask_rx_interrupts(struct s5p_cec_dev *cec)
{
u8 reg;
reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
reg &= ~S5P_CEC_IRQ_RX_DONE;
reg &= ~S5P_CEC_IRQ_RX_ERROR;
writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
}
void s5p_cec_mask_tx_interrupts(struct s5p_cec_dev *cec)
{
u8 reg;
reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
reg |= S5P_CEC_IRQ_TX_DONE;
reg |= S5P_CEC_IRQ_TX_ERROR;
writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
}
void s5p_cec_unmask_tx_interrupts(struct s5p_cec_dev *cec)
{
u8 reg;
reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
reg &= ~S5P_CEC_IRQ_TX_DONE;
reg &= ~S5P_CEC_IRQ_TX_ERROR;
writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
}
void s5p_cec_reset(struct s5p_cec_dev *cec)
{
u8 reg;
writeb(S5P_CEC_RX_CTRL_RESET, cec->reg + S5P_CEC_RX_CTRL);
writeb(S5P_CEC_TX_CTRL_RESET, cec->reg + S5P_CEC_TX_CTRL);
reg = readb(cec->reg + 0xc4);
reg &= ~0x1;
writeb(reg, cec->reg + 0xc4);
}
void s5p_cec_tx_reset(struct s5p_cec_dev *cec)
{
writeb(S5P_CEC_TX_CTRL_RESET, cec->reg + S5P_CEC_TX_CTRL);
}
void s5p_cec_rx_reset(struct s5p_cec_dev *cec)
{
u8 reg;
writeb(S5P_CEC_RX_CTRL_RESET, cec->reg + S5P_CEC_RX_CTRL);
reg = readb(cec->reg + 0xc4);
reg &= ~0x1;
writeb(reg, cec->reg + 0xc4);
}
void s5p_cec_threshold(struct s5p_cec_dev *cec)
{
writeb(CEC_FILTER_THRESHOLD, cec->reg + S5P_CEC_RX_FILTER_TH);
writeb(0, cec->reg + S5P_CEC_RX_FILTER_CTRL);
}
void s5p_cec_copy_packet(struct s5p_cec_dev *cec, char *data,
size_t count, u8 retries)
{
int i = 0;
u8 reg;
while (i < count) {
writeb(data[i], cec->reg + (S5P_CEC_TX_BUFF0 + (i * 4)));
i++;
}
writeb(count, cec->reg + S5P_CEC_TX_BYTES);
reg = readb(cec->reg + S5P_CEC_TX_CTRL);
reg |= S5P_CEC_TX_CTRL_START;
reg &= ~0x70;
reg |= retries << 4;
if ((data[0] & CEC_MESSAGE_BROADCAST_MASK) == CEC_MESSAGE_BROADCAST) {
dev_dbg(cec->dev, "Broadcast");
reg |= S5P_CEC_TX_CTRL_BCAST;
} else {
dev_dbg(cec->dev, "No Broadcast");
reg &= ~S5P_CEC_TX_CTRL_BCAST;
}
writeb(reg, cec->reg + S5P_CEC_TX_CTRL);
dev_dbg(cec->dev, "cec-tx: cec count (%zu): %*ph", count,
(int)count, data);
}
void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr)
{
writeb(addr & 0x0F, cec->reg + S5P_CEC_LOGIC_ADDR);
}
u32 s5p_cec_get_status(struct s5p_cec_dev *cec)
{
u32 status = 0;
status = readb(cec->reg + S5P_CEC_STATUS_0) & 0xf;
status |= (readb(cec->reg + S5P_CEC_TX_STAT1) & 0xf) << 4;
status |= readb(cec->reg + S5P_CEC_STATUS_1) << 8;
status |= readb(cec->reg + S5P_CEC_STATUS_2) << 16;
status |= readb(cec->reg + S5P_CEC_STATUS_3) << 24;
dev_dbg(cec->dev, "status = 0x%x!\n", status);
return status;
}
void s5p_clr_pending_tx(struct s5p_cec_dev *cec)
{
writeb(S5P_CEC_IRQ_TX_DONE | S5P_CEC_IRQ_TX_ERROR,
cec->reg + S5P_CEC_IRQ_CLEAR);
}
void s5p_clr_pending_rx(struct s5p_cec_dev *cec)
{
writeb(S5P_CEC_IRQ_RX_DONE | S5P_CEC_IRQ_RX_ERROR,
cec->reg + S5P_CEC_IRQ_CLEAR);
}
void s5p_cec_get_rx_buf(struct s5p_cec_dev *cec, u32 size, u8 *buffer)
{
u32 i = 0;
char debug[40];
while (i < size) {
buffer[i] = readb(cec->reg + S5P_CEC_RX_BUFF0 + (i * 4));
sprintf(debug + i * 2, "%02x ", buffer[i]);
i++;
}
dev_dbg(cec->dev, "cec-rx: cec size(%d): %s", size, debug);
}
@@ -0,0 +1,93 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* drivers/media/platform/s5p-cec/regs-cec.h
*
* Copyright (c) 2010 Samsung Electronics
* http://www.samsung.com/
*
* register header file for Samsung TVOUT driver
*/
#ifndef __EXYNOS_REGS__H
#define __EXYNOS_REGS__H
/*
* Register part
*/
#define S5P_CEC_STATUS_0 (0x0000)
#define S5P_CEC_STATUS_1 (0x0004)
#define S5P_CEC_STATUS_2 (0x0008)
#define S5P_CEC_STATUS_3 (0x000C)
#define S5P_CEC_IRQ_MASK (0x0010)
#define S5P_CEC_IRQ_CLEAR (0x0014)
#define S5P_CEC_LOGIC_ADDR (0x0020)
#define S5P_CEC_DIVISOR_0 (0x0030)
#define S5P_CEC_DIVISOR_1 (0x0034)
#define S5P_CEC_DIVISOR_2 (0x0038)
#define S5P_CEC_DIVISOR_3 (0x003C)
#define S5P_CEC_TX_CTRL (0x0040)
#define S5P_CEC_TX_BYTES (0x0044)
#define S5P_CEC_TX_STAT0 (0x0060)
#define S5P_CEC_TX_STAT1 (0x0064)
#define S5P_CEC_TX_BUFF0 (0x0080)
#define S5P_CEC_TX_BUFF1 (0x0084)
#define S5P_CEC_TX_BUFF2 (0x0088)
#define S5P_CEC_TX_BUFF3 (0x008C)
#define S5P_CEC_TX_BUFF4 (0x0090)
#define S5P_CEC_TX_BUFF5 (0x0094)
#define S5P_CEC_TX_BUFF6 (0x0098)
#define S5P_CEC_TX_BUFF7 (0x009C)
#define S5P_CEC_TX_BUFF8 (0x00A0)
#define S5P_CEC_TX_BUFF9 (0x00A4)
#define S5P_CEC_TX_BUFF10 (0x00A8)
#define S5P_CEC_TX_BUFF11 (0x00AC)
#define S5P_CEC_TX_BUFF12 (0x00B0)
#define S5P_CEC_TX_BUFF13 (0x00B4)
#define S5P_CEC_TX_BUFF14 (0x00B8)
#define S5P_CEC_TX_BUFF15 (0x00BC)
#define S5P_CEC_RX_CTRL (0x00C0)
#define S5P_CEC_RX_STAT0 (0x00E0)
#define S5P_CEC_RX_STAT1 (0x00E4)
#define S5P_CEC_RX_BUFF0 (0x0100)
#define S5P_CEC_RX_BUFF1 (0x0104)
#define S5P_CEC_RX_BUFF2 (0x0108)
#define S5P_CEC_RX_BUFF3 (0x010C)
#define S5P_CEC_RX_BUFF4 (0x0110)
#define S5P_CEC_RX_BUFF5 (0x0114)
#define S5P_CEC_RX_BUFF6 (0x0118)
#define S5P_CEC_RX_BUFF7 (0x011C)
#define S5P_CEC_RX_BUFF8 (0x0120)
#define S5P_CEC_RX_BUFF9 (0x0124)
#define S5P_CEC_RX_BUFF10 (0x0128)
#define S5P_CEC_RX_BUFF11 (0x012C)
#define S5P_CEC_RX_BUFF12 (0x0130)
#define S5P_CEC_RX_BUFF13 (0x0134)
#define S5P_CEC_RX_BUFF14 (0x0138)
#define S5P_CEC_RX_BUFF15 (0x013C)
#define S5P_CEC_RX_FILTER_CTRL (0x0180)
#define S5P_CEC_RX_FILTER_TH (0x0184)
/*
* Bit definition part
*/
#define S5P_CEC_IRQ_TX_DONE (1<<0)
#define S5P_CEC_IRQ_TX_ERROR (1<<1)
#define S5P_CEC_IRQ_RX_DONE (1<<4)
#define S5P_CEC_IRQ_RX_ERROR (1<<5)
#define S5P_CEC_TX_CTRL_START (1<<0)
#define S5P_CEC_TX_CTRL_BCAST (1<<1)
#define S5P_CEC_TX_CTRL_RETRY (0x04<<4)
#define S5P_CEC_TX_CTRL_RESET (1<<7)
#define S5P_CEC_RX_CTRL_ENABLE (1<<0)
#define S5P_CEC_RX_CTRL_RESET (1<<7)
#define S5P_CEC_LOGIC_ADDR_MASK (0xF)
/* PMU Registers for PHY */
#define EXYNOS_HDMI_PHY_CONTROL 0x700
#endif /* __EXYNOS_REGS__H */
@@ -0,0 +1,309 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* drivers/media/platform/s5p-cec/s5p_cec.c
*
* Samsung S5P CEC driver
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
*
* This driver is based on the "cec interface driver for exynos soc" by
* SangPil Moon.
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <media/cec.h>
#include <media/cec-notifier.h>
#include "exynos_hdmi_cec.h"
#include "regs-cec.h"
#include "s5p_cec.h"
#define CEC_NAME "s5p-cec"
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");
static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable)
{
int ret;
struct s5p_cec_dev *cec = cec_get_drvdata(adap);
if (enable) {
ret = pm_runtime_resume_and_get(cec->dev);
if (ret < 0)
return ret;
s5p_cec_reset(cec);
s5p_cec_set_divider(cec);
s5p_cec_threshold(cec);
s5p_cec_unmask_tx_interrupts(cec);
s5p_cec_unmask_rx_interrupts(cec);
s5p_cec_enable_rx(cec);
} else {
s5p_cec_mask_tx_interrupts(cec);
s5p_cec_mask_rx_interrupts(cec);
pm_runtime_put(cec->dev);
}
return 0;
}
static int s5p_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
{
struct s5p_cec_dev *cec = cec_get_drvdata(adap);
s5p_cec_set_addr(cec, addr);
return 0;
}
static int s5p_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
u32 signal_free_time, struct cec_msg *msg)
{
struct s5p_cec_dev *cec = cec_get_drvdata(adap);
/*
* Unclear if 0 retries are allowed by the hardware, so have 1 as
* the minimum.
*/
s5p_cec_copy_packet(cec, msg->msg, msg->len, max(1, attempts - 1));
return 0;
}
static irqreturn_t s5p_cec_irq_handler(int irq, void *priv)
{
struct s5p_cec_dev *cec = priv;
u32 status = 0;
status = s5p_cec_get_status(cec);
dev_dbg(cec->dev, "irq received\n");
if (status & CEC_STATUS_TX_DONE) {
if (status & CEC_STATUS_TX_NACK) {
dev_dbg(cec->dev, "CEC_STATUS_TX_NACK set\n");
cec->tx = STATE_NACK;
} else if (status & CEC_STATUS_TX_ERROR) {
dev_dbg(cec->dev, "CEC_STATUS_TX_ERROR set\n");
cec->tx = STATE_ERROR;
} else {
dev_dbg(cec->dev, "CEC_STATUS_TX_DONE\n");
cec->tx = STATE_DONE;
}
s5p_clr_pending_tx(cec);
}
if (status & CEC_STATUS_RX_DONE) {
if (status & CEC_STATUS_RX_ERROR) {
dev_dbg(cec->dev, "CEC_STATUS_RX_ERROR set\n");
s5p_cec_rx_reset(cec);
s5p_cec_enable_rx(cec);
} else {
dev_dbg(cec->dev, "CEC_STATUS_RX_DONE set\n");
if (cec->rx != STATE_IDLE)
dev_dbg(cec->dev, "Buffer overrun (worker did not process previous message)\n");
cec->rx = STATE_BUSY;
cec->msg.len = status >> 24;
if (cec->msg.len > CEC_MAX_MSG_SIZE)
cec->msg.len = CEC_MAX_MSG_SIZE;
cec->msg.rx_status = CEC_RX_STATUS_OK;
s5p_cec_get_rx_buf(cec, cec->msg.len,
cec->msg.msg);
cec->rx = STATE_DONE;
s5p_cec_enable_rx(cec);
}
/* Clear interrupt pending bit */
s5p_clr_pending_rx(cec);
}
return IRQ_WAKE_THREAD;
}
static irqreturn_t s5p_cec_irq_handler_thread(int irq, void *priv)
{
struct s5p_cec_dev *cec = priv;
dev_dbg(cec->dev, "irq processing thread\n");
switch (cec->tx) {
case STATE_DONE:
cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
cec->tx = STATE_IDLE;
break;
case STATE_NACK:
cec_transmit_done(cec->adap,
CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_NACK,
0, 1, 0, 0);
cec->tx = STATE_IDLE;
break;
case STATE_ERROR:
cec_transmit_done(cec->adap,
CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_ERROR,
0, 0, 0, 1);
cec->tx = STATE_IDLE;
break;
case STATE_BUSY:
dev_err(cec->dev, "state set to busy, this should not occur here\n");
break;
default:
break;
}
switch (cec->rx) {
case STATE_DONE:
cec_received_msg(cec->adap, &cec->msg);
cec->rx = STATE_IDLE;
break;
default:
break;
}
return IRQ_HANDLED;
}
static const struct cec_adap_ops s5p_cec_adap_ops = {
.adap_enable = s5p_cec_adap_enable,
.adap_log_addr = s5p_cec_adap_log_addr,
.adap_transmit = s5p_cec_adap_transmit,
};
static int s5p_cec_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device *hdmi_dev;
struct s5p_cec_dev *cec;
bool needs_hpd = of_property_read_bool(pdev->dev.of_node, "needs-hpd");
int ret;
hdmi_dev = cec_notifier_parse_hdmi_phandle(dev);
if (IS_ERR(hdmi_dev))
return PTR_ERR(hdmi_dev);
cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
if (!cec)
return -ENOMEM;
cec->dev = dev;
cec->irq = platform_get_irq(pdev, 0);
if (cec->irq < 0)
return cec->irq;
ret = devm_request_threaded_irq(dev, cec->irq, s5p_cec_irq_handler,
s5p_cec_irq_handler_thread, 0, pdev->name, cec);
if (ret)
return ret;
cec->clk = devm_clk_get(dev, "hdmicec");
if (IS_ERR(cec->clk))
return PTR_ERR(cec->clk);
cec->pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
"samsung,syscon-phandle");
if (IS_ERR(cec->pmu))
return -EPROBE_DEFER;
cec->reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cec->reg))
return PTR_ERR(cec->reg);
cec->adap = cec_allocate_adapter(&s5p_cec_adap_ops, cec, CEC_NAME,
CEC_CAP_DEFAULTS | (needs_hpd ? CEC_CAP_NEEDS_HPD : 0) |
CEC_CAP_CONNECTOR_INFO, 1);
ret = PTR_ERR_OR_ZERO(cec->adap);
if (ret)
return ret;
cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
cec->adap);
if (!cec->notifier) {
ret = -ENOMEM;
goto err_delete_adapter;
}
ret = cec_register_adapter(cec->adap, &pdev->dev);
if (ret)
goto err_notifier;
platform_set_drvdata(pdev, cec);
pm_runtime_enable(dev);
dev_dbg(dev, "successfully probed\n");
return 0;
err_notifier:
cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
err_delete_adapter:
cec_delete_adapter(cec->adap);
return ret;
}
static void s5p_cec_remove(struct platform_device *pdev)
{
struct s5p_cec_dev *cec = platform_get_drvdata(pdev);
cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
cec_unregister_adapter(cec->adap);
pm_runtime_disable(&pdev->dev);
}
static int __maybe_unused s5p_cec_runtime_suspend(struct device *dev)
{
struct s5p_cec_dev *cec = dev_get_drvdata(dev);
clk_disable_unprepare(cec->clk);
return 0;
}
static int __maybe_unused s5p_cec_runtime_resume(struct device *dev)
{
struct s5p_cec_dev *cec = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(cec->clk);
if (ret < 0)
return ret;
return 0;
}
static const struct dev_pm_ops s5p_cec_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(s5p_cec_runtime_suspend, s5p_cec_runtime_resume,
NULL)
};
static const struct of_device_id s5p_cec_match[] = {
{
.compatible = "samsung,s5p-cec",
},
{},
};
MODULE_DEVICE_TABLE(of, s5p_cec_match);
static struct platform_driver s5p_cec_pdrv = {
.probe = s5p_cec_probe,
.remove = s5p_cec_remove,
.driver = {
.name = CEC_NAME,
.of_match_table = s5p_cec_match,
.pm = &s5p_cec_pm_ops,
},
};
module_platform_driver(s5p_cec_pdrv);
MODULE_AUTHOR("Kamil Debski <kamil@wypas.org>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Samsung S5P CEC driver");
@@ -0,0 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* drivers/media/platform/s5p-cec/s5p_cec.h
*
* Samsung S5P HDMI CEC driver
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
*/
#ifndef _S5P_CEC_H_
#define _S5P_CEC_H_ __FILE__
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <media/cec.h>
#include "exynos_hdmi_cec.h"
#include "regs-cec.h"
#include "s5p_cec.h"
#define CEC_NAME "s5p-cec"
#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_NACK (1 << 4)
#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)
#define CEC_WORKER_TX_DONE (1 << 0)
#define CEC_WORKER_RX_MSG (1 << 1)
/* CEC Rx buffer size */
#define CEC_RX_BUFF_SIZE 16
/* CEC Tx buffer size */
#define CEC_TX_BUFF_SIZE 16
enum cec_state {
STATE_IDLE,
STATE_BUSY,
STATE_DONE,
STATE_NACK,
STATE_ERROR
};
struct cec_notifier;
struct s5p_cec_dev {
struct cec_adapter *adap;
struct clk *clk;
struct device *dev;
struct mutex lock;
struct regmap *pmu;
struct cec_notifier *notifier;
int irq;
void __iomem *reg;
enum cec_state rx;
enum cec_state tx;
struct cec_msg msg;
};
#endif /* _S5P_CEC_H_ */