From 0febce26f48064580e3578a98e785eb87916895a Mon Sep 17 00:00:00 2001 From: hjc Date: Thu, 3 Jul 2014 19:40:26 +0800 Subject: [PATCH] rk3036 hdmi: add basic version --- arch/arm/boot/dts/rk3036.dtsi | 13 ++++ drivers/video/rockchip/hdmi/chips/Kconfig | 2 +- .../rockchip/hdmi/chips/rk616/rk616_hdmi.c | 49 ++++++++------- .../rockchip/hdmi/chips/rk616/rk616_hdmi.h | 1 + .../rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c | 59 ++++++++++++++----- .../rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h | 25 +++++--- drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c | 2 +- 7 files changed, 102 insertions(+), 49 deletions(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index c8616f020bbc..bbb300c454a4 100755 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -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 = ; + 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"; diff --git a/drivers/video/rockchip/hdmi/chips/Kconfig b/drivers/video/rockchip/hdmi/chips/Kconfig index b8797ffdeab8..8f72dfed7b94 100755 --- a/drivers/video/rockchip/hdmi/chips/Kconfig +++ b/drivers/video/rockchip/hdmi/chips/Kconfig @@ -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 diff --git a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c index 1262dd579c9c..83bd233b8ac7 100755 --- a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c +++ b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c @@ -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, }; diff --git a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h index 35ff0927a75e..b104ee187868 100755 --- a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h +++ b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h @@ -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; diff --git a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c index 4b51345b6a3f..26d91496d974 100755 --- a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c +++ b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c @@ -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); diff --git a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h index 1d3c24417d75..41c88e6b0720 100755 --- a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h +++ b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h @@ -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); diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c b/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c index fe65b3760f76..cb61763ac68c 100755 --- a/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c +++ b/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c @@ -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 -- 2.34.1