rk3036 hdmi: add basic version

This commit is contained in:
hjc
2014-07-03 19:40:26 +08:00
parent a0ebfaf4de
commit 0febce26f4
7 changed files with 102 additions and 49 deletions

View File

@@ -399,6 +399,19 @@
clocks = <&clk_gates1 6>, <&clk_gates7 3>;
clock-names = "clk_usbphy1", "hclk_usb1";
};
hdmi: hdmi@20034000 {
compatible = "rockchip,rk3036-hdmi";
reg = <0x20034000 0x4000>;
interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
rockchip,hdmi_lcdc_source = <0>;
//pinctrl-names = "default", "gpio";
//pinctrl-0 = <&i2c5_sda &i2c5_scl>;
//pinctrl-1 = <&i2c5_gpio>;
clocks = <&clk_gates3 8>;
clock-names = "pclk_hdmi";
status = "disabled";
};
vpu: vpu_service@10108000 {
compatible = "vpu_service";

View File

@@ -39,7 +39,7 @@ endif
config HDMI_RK616
bool "RK616 HDMI support"
depends on MFD_RK616 || ARCH_RK3026
#depends on MFD_RK616 || ARCH_RK3026
default y
help
Support rk616 hdmi if you say y here

View File

@@ -92,7 +92,7 @@ static const struct file_operations rk616_hdmi_reg_fops = {
};
#endif
#if defined(CONFIG_ARCH_RK3026)
#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
static int rk616_hdmi_clk_enable(struct rk_hdmi_device *hdmi_dev)
{
if (!hdmi_dev->clk_on) {
@@ -261,7 +261,7 @@ static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
disable_irq_nosync(hdmi_drv->irq);
queue_work(hdmi_drv->workqueue, rk616_irq_work_struct);
} else {
/* 3028a hdmi */
/* 3028a/3036 hdmi */
if ((hdmi_drv->suspend == 0) && (hdmi_drv->enable == 1)) {
hdmi_dbg(hdmi_drv->dev,
"line = %d, rk616_hdmi_irq irq triggered.\n",
@@ -284,7 +284,7 @@ static int rk616_hdmi_drv_init(struct hdmi *hdmi_drv)
lcdc_id = (screen.lcdc_id == 0) ? 1 : 0;
/* lcdc source select */
/* wait to modify!!
#if defined(CONFIG_ARCH_RK3026)
#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
grf_writel(HDMI_SEL_LCDC(lcdc_id), RK3036_GRF_SOC_CON6);
#endif
*/
@@ -310,10 +310,20 @@ static int rk616_hdmi_drv_init(struct hdmi *hdmi_drv)
return ret;
}
#if defined(CONFIG_OF)
static const struct of_device_id rk616_hdmi_of_match[] = {
{.compatible = "rockchip,rk616-hdmi",},
{.compatible = "rockchip,rk3036-hdmi",},
{}
};
MODULE_DEVICE_TABLE(of, rk616_hdmi_of_match);
#endif
static int rk616_hdmi_probe(struct platform_device *pdev)
{
int ret;
struct rk_hdmi_device *hdmi_dev;
//struct rk_hdmi_device *hdmi_dev;
struct hdmi *hdmi_drv;
struct resource __maybe_unused *mem;
struct resource __maybe_unused *res;
@@ -330,7 +340,7 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hdmi_dev);
spin_lock_init(&hdmi_dev->reg_lock);
#ifdef CONFIG_ARCH_RK3026
#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
hdmi_dev->rk616_drv = NULL;
#else
hdmi_dev->rk616_drv = dev_get_drvdata(pdev->dev.parent);
@@ -354,7 +364,7 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&(hdmi_drv->delay_work), hdmi_work);
INIT_DELAYED_WORK(&hdmi_dev->rk616_delay_work, rk616_delay_work_func);
#ifdef CONFIG_ARCH_RK3026
#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
/* enable clk */
hdmi_dev->hclk = devm_clk_get(hdmi_drv->dev, "pclk_hdmi");
if (IS_ERR(hdmi_dev->hclk)) {
@@ -362,12 +372,12 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
ret = -ENXIO;
goto err1;
}
rk616_hdmi_clk_enable(); /* enable clk may move to irq func */
rk616_hdmi_clk_enable(hdmi_dev); /* enable clk may move to irq func */
/* request and remap iomem */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(hdmi_dev->dev, "Unable to get register resource\n");
dev_err(hdmi_drv->dev, "Unable to get register resource\n");
ret = -ENXIO;
goto err2;
}
@@ -384,8 +394,8 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
/* get the IRQ */
hdmi_drv->irq = platform_get_irq(pdev, 0);
if (hdmi_drv->irq <= 0) {
dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n",
hdmi->irq);
dev_err(hdmi_drv->dev, "failed to get hdmi irq resource (%d).\n",
hdmi_drv->irq);
hdmi_drv->irq = 0;
} else {
/* request the IRQ */
@@ -459,7 +469,7 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
dev_info(hdmi_drv->dev, "rk616 hdmi probe success.\n");
return 0;
#if defined(CONFIG_ARCH_RK3026)
#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
err2:
rk616_hdmi_clk_disable(hdmi_dev);
#endif
@@ -520,7 +530,8 @@ static int rk616_hdmi_remove(struct platform_device *pdev)
static void rk616_hdmi_shutdown(struct platform_device *pdev)
{
struct hdmi *hdmi_drv;
struct rk_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
struct hdmi *hdmi_drv = NULL;
if (hdmi_dev) {
hdmi_drv = &hdmi_dev->driver;
@@ -541,26 +552,14 @@ static void rk616_hdmi_shutdown(struct platform_device *pdev)
hdmi_dbg(hdmi_drv->dev, "rk616 hdmi shut down.\n");
}
#if defined(CONFIG_OF)
static const struct of_device_id rk616_hdmi_of_match[] = {
{.compatible = "rockchip,rk616-hdmi",},
{}
};
MODULE_DEVICE_TABLE(of, rk616_hdmi_of_match);
#endif
static struct platform_driver rk616_hdmi_driver = {
.probe = rk616_hdmi_probe,
.remove = rk616_hdmi_remove,
.driver = {
#ifdef CONFIG_ARCH_RK3026
.name = "rk3026-hdmi",
#else
.name = "rk616-hdmi",
#endif
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(rk616_hdmi_of_match),
.of_match_table = of_match_ptr(rk616_hdmi_of_match),
},
.shutdown = rk616_hdmi_shutdown,
};

View File

@@ -30,6 +30,7 @@ struct rk_hdmi_device {
int regsize_phy;
struct clk *pd;
struct clk *hclk; /* HDMI AHP clk */
struct clk *pclk; /* HDMI APB clk */
struct delayed_work rk616_delay_work;
struct work_struct rk616_irq_work_struct;
struct mfd_rk616 *rk616_drv;

View File

@@ -5,7 +5,8 @@
#include "rk616_hdmi.h"
#include "rk616_hdmi_hw.h"
#ifndef CONFIG_ARCH_RK3026
#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
static int rk616_set_polarity(struct mfd_rk616 *rk616_drv, int vic)
{
u32 val;
@@ -129,11 +130,16 @@ static void rk616_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
hdmi_writel(hdmi_dev, PHY_DRIVER, 0x99);
hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x0f);
}
hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x2d);
hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x2c);
hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x28);
hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x20);
#ifndef SOC_CONFIG_RK3036
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2d);
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2c);
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x28);
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x20);
#else
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x15);
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x14);
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x10);
#endif
hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
hdmi_writel(hdmi_dev, 0xce, 0x00);
hdmi_writel(hdmi_dev, 0xce, 0x01);
@@ -149,7 +155,11 @@ static void rk616_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x2f);
#ifndef SOC_CONFIG_RK3036
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2f);
#else
hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x17);
#endif
break;
default:
hdmi_dbg(hdmi_drv->dev, "unkown rk616 hdmi pwr mode %d\n",
@@ -259,8 +269,12 @@ int rk616_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
}
}
}
hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_HOTPLUG);
//close edid irq
#ifndef SOC_CONFIG_RK3036
hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_HOTPLUG);
#else
hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
#endif
enable_irq(hdmi_drv->irq);
return ret;
@@ -570,10 +584,17 @@ void rk616_hdmi_work(struct hdmi *hdmi_drv)
struct rk_hdmi_device,
driver);
hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &interrupt);
if (interrupt)
hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
#ifndef SOC_CONFIG_RK3036
hdmi_readl(hdmi_dev, INTERRUPT_STATUS1,&interrupt);
if(interrupt){
hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
}
#else
hdmi_readl(hdmi_dev, HDMI_STATUS,&interrupt);
if(interrupt){
hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
}
#endif
if (interrupt & m_HOTPLUG) {
if (hdmi_drv->state == HDMI_SLEEP)
hdmi_drv->state = WAIT_HOTPLUG;
@@ -602,14 +623,20 @@ static void rk616_hdmi_reset(struct hdmi *hdmi_drv)
msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
#ifndef SOC_CONFIG_RK3036
hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_HOTPLUG);
#else
hdmi_readl(hdmi_dev, HDMI_STATUS,&val);//enable hpg
val |= m_MASK_INT_HOTPLUG;
hdmi_writel(hdmi_dev, HDMI_STATUS,val);
#endif
rk616_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
}
int rk616_hdmi_initial(struct hdmi *hdmi_drv)
{
int rc = HDMI_ERROR_SUCESS;
#ifndef CONFIG_ARCH_RK3026
#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
struct rk_hdmi_device,
driver);
@@ -624,9 +651,11 @@ int rk616_hdmi_initial(struct hdmi *hdmi_drv)
hdmi_drv->detect_hotplug = rk616_hdmi_detect_hotplug;
hdmi_drv->read_edid = rk616_hdmi_read_edid;
#ifdef CONFIG_ARCH_RK3026
#if defined(CONFIG_ARCH_RK3026)
rk3028_hdmi_reset_pclk();
rk616_hdmi_reset(hdmi_drv);
#elif defined(SOC_CONFIG_RK3036)
rk616_hdmi_reset(hdmi_drv);
#else
hdmi_drv->set_vif = rk616_hdmi_set_vif;
rk616_hdmi_reset(hdmi_drv);

View File

@@ -1,6 +1,8 @@
#ifndef _RK616_HDMI_HW_H
#define _RK616_HDMI_HW_H
#define SOC_CONFIG_RK3036
#define RK616_HDMI_BASE 0x400
enum PWR_MODE {
NORMAL,
@@ -223,7 +225,9 @@ enum {
#define INTERRUPT_MASK1 0xc0
#define INTERRUPT_STATUS1 0xc1
#ifndef SOC_CONFIG_RK3036
#define m_INT_HOTPLUG (1 << 7)
#endif
#define m_INT_ACTIVE_VSYNC (1 << 5)
#define m_INT_EDID_READY (1 << 2)
@@ -234,9 +238,15 @@ enum {
#define m_INT_HDCP_OK (1 << 4)
#define HDMI_STATUS 0xc8
#define m_HOTPLUG (1 << 7)
#define m_DDC_SDA (1 << 5)
#define m_DDC_SDC (1 << 4)
#define m_HOTPLUG (1 << 7)
#ifndef SOC_CONFIG_RK3036
#define m_DDC_SDA (1 << 5)
#define m_DDC_SDC (1 << 4)
#else
#define m_MASK_INT_HOTPLUG (1 << 5)
#define m_INT_HOTPLUG (1 << 1)
#endif
#define HDMI_COLORBAR 0xc9
@@ -282,7 +292,7 @@ enum {
#define PHY_PRE_DIV_RATIO 0xed
#define v_PRE_DIV_RATIO(n) (n & 0x1f)
#ifndef CONFIG_ARCH_RK3026
#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
static inline int hdmi_readl(struct rk_hdmi_device *hdmi_dev,
u16 offset, u32 *val)
{
@@ -342,11 +352,11 @@ static inline int hdmi_msk_reg(struct rk_hdmi_device *hdmi_dev, u16 offset,
int ret = 0;
u32 temp;
temp = readl_relaxed(hdmi->regbase + (offset) * 0x04) & (0xFF - (msk));
writel_relaxed(temp | ((val) & (msk)), hdmi->regbase + (offset) * 0x04);
temp = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04) & (0xFF - (msk));
writel_relaxed(temp | ((val) & (msk)), hdmi_dev->regbase + (offset) * 0x04);
return ret;
}
#if defined(CONFIG_ARCH_RK3026)
static inline void rk3028_hdmi_reset_pclk(void)
{
writel_relaxed(0x00010001, RK2928_CRU_BASE + 0x128);
@@ -354,6 +364,7 @@ static inline void rk3028_hdmi_reset_pclk(void)
writel_relaxed(0x00010000, RK2928_CRU_BASE + 0x128);
}
#endif
#endif
extern int rk616_hdmi_initial(struct hdmi *hdmi);
extern void rk616_hdmi_work(struct hdmi *hdmi);

View File

@@ -124,7 +124,7 @@ int hdmi_set_info(struct rk_screen *screen, unsigned int vic)
screen->hdmi_resolution = hdmi_mode[i].flag;
/* Pin polarity */
#if defined(CONFIG_HDMI_RK616) && !defined(CONFIG_ARCH_RK3026)
#if defined(CONFIG_HDMI_RK616) && !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
screen->pin_hsync = 0;
screen->pin_vsync = 0;
#else