video: rockchip: hdmi: support rk3399 hdmi
authorxuhuicong <xhc@rock-chips.com>
Tue, 12 Apr 2016 01:16:30 +0000 (09:16 +0800)
committerGerrit Code Review <gerrit@rock-chips.com>
Tue, 10 May 2016 02:27:18 +0000 (10:27 +0800)
RK3399 hdmi register layout is similar with rk3288 and rk3368, so most
code can reuse. but hdmi resign is upgrade from 20 to 21 so it has a
little diffrence. and the hdmi phy clk is Independent from dclk too.

Change-Id: I83b30c92d9572fc9ceaf52777d224e5cec1823be
Signed-off-by: xuhuicong <xhc@rock-chips.com>
Documentation/devicetree/bindings/video/rockchip_hdmi.txt
drivers/video/rockchip/hdmi/rockchip-hdmi.h
drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c
drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c

index 806527857ae2262674a2cd38f5973ad13765fb5a..67c9080063a3cdd84196d9359e4b3ad692b561a2 100644 (file)
@@ -2,10 +2,12 @@ Device-Tree bindings for rockchip hdmi driver
 
 Required properties:
 - compatible: value should be following:
-       "rockchip,rk3288-hdmi",
-       "rockchip,rk3368-hdmi",
        "rockchip,rk3036-hdmi",
        "rockchip,rk312x-hdmi",
+       "rockchip,rk3288-hdmi",
+       "rockchip,rk3366-hdmi",
+       "rockchip,rk3368-hdmi",
+       "rockchip,rk3399-hdmi",
 - reg: physical base address of the hdmi and length of memory mapped
         region.
 - interrupts: interrupt number to the cpu.
index 953f054792b7320c2fa7068e436bb8b088d85793..ec5dc21438e29121c5872a54de3545ee12e51e78 100644 (file)
@@ -377,6 +377,7 @@ enum {
        HDMI_SOC_RK3288,
        HDMI_SOC_RK3366,
        HDMI_SOC_RK3368,
+       HDMI_SOC_RK3399,
 };
 
 /* HDMI Information */
index 86cedf5f548c69d949fc816089b3d99e4ce3d966..2b04162fd02dfe1e6b92b082692df038e3150842 100644 (file)
@@ -20,8 +20,9 @@
 #include "rockchip_hdmiv2.h"
 #include "rockchip_hdmiv2_hw.h"
 
-#define HDMI_SEL_LCDC(x)       ((((x) & 1) << 4) | (1 << 20))
+#define HDMI_SEL_LCDC(x, bit)  ((((x) & 1) << bit) | (1 << (16 + bit)))
 #define grf_writel(v, offset)  writel_relaxed(v, RK_GRF_VIRT + offset)
+#define GRF_SOC_CON20 0x6250
 
 static struct hdmi_dev *hdmi_dev;
 
@@ -210,7 +211,8 @@ void ext_pll_set_27m_out(void)
 static int rockchip_hdmiv2_clk_enable(struct hdmi_dev *hdmi_dev)
 {
        if (hdmi_dev->soctype == HDMI_SOC_RK322X ||
-           hdmi_dev->soctype == HDMI_SOC_RK3366) {
+           hdmi_dev->soctype == HDMI_SOC_RK3366 ||
+           hdmi_dev->soctype == HDMI_SOC_RK3399) {
                if ((hdmi_dev->clk_on & HDMI_EXT_PHY_CLK_ON) == 0) {
                        if (!hdmi_dev->pclk_phy) {
                                if (hdmi_dev->soctype == HDMI_SOC_RK322X)
@@ -401,6 +403,7 @@ static const struct of_device_id rk_hdmi_dt_ids[] = {
        {.compatible = "rockchip,rk3288-hdmi",},
        {.compatible = "rockchip,rk3366-hdmi",},
        {.compatible = "rockchip,rk3368-hdmi",},
+       {.compatible = "rockchip,rk3399-hdmi",},
        {}
 };
 
@@ -422,6 +425,8 @@ static int rockchip_hdmiv2_parse_dt(struct hdmi_dev *hdmi_dev)
                hdmi_dev->soctype = HDMI_SOC_RK322X;
        } else if (!strcmp(match->compatible, "rockchip,rk3366-hdmi")) {
                hdmi_dev->soctype = HDMI_SOC_RK3366;
+       } else if (!strcmp(match->compatible, "rockchip,rk3399-hdmi")) {
+               hdmi_dev->soctype = HDMI_SOC_RK3399;
        } else {
                pr_err("It is not a valid rockchip soc!");
                return -ENOMEM;
@@ -558,10 +563,14 @@ static int rockchip_hdmiv2_probe(struct platform_device *pdev)
        }
        /*lcdc source select*/
        if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
-               grf_writel(HDMI_SEL_LCDC(rk_hdmi_property.videosrc),
+               grf_writel(HDMI_SEL_LCDC(rk_hdmi_property.videosrc, 4),
                           RK3288_GRF_SOC_CON6);
                /* select GPIO7_C0 as cec pin */
                grf_writel(((1 << 12) | (1 << 28)), RK3288_GRF_SOC_CON8);
+       } else if (hdmi_dev->soctype == HDMI_SOC_RK3399) {
+               regmap_write(hdmi_dev->grf_base,
+                            GRF_SOC_CON20,
+                            HDMI_SEL_LCDC(rk_hdmi_property.videosrc, 6));
        }
        rockchip_hdmiv2_dev_init_ops(&rk_hdmi_ops);
        /* Register HDMI device */
@@ -605,6 +614,19 @@ static int rockchip_hdmiv2_probe(struct platform_device *pdev)
                                                SUPPORT_YUV420 |
                                                SUPPORT_YCBCR_INPUT |
                                                SUPPORT_TMDS_600M;
+       } else if (hdmi_dev->soctype == HDMI_SOC_RK3399) {
+               rk_hdmi_property.feature |=
+                               SUPPORT_DEEP_10BIT |
+                               SUPPORT_YCBCR_INPUT |
+                               SUPPORT_1080I |
+                               SUPPORT_480I_576I;
+               if (rk_hdmi_property.videosrc == DISPLAY_SOURCE_LCDC0)
+                       rk_hdmi_property.feature |=
+                                               SUPPORT_4K |
+                                               SUPPORT_4K_4096 |
+                                               SUPPORT_YUV420 |
+                                               SUPPORT_YCBCR_INPUT |
+                                               SUPPORT_TMDS_600M;
        } else {
                ret = -ENXIO;
                goto failed1;
index d39998d259c6c33ef7895e65db9c94232ecc0b03..6c85f076528aa7afaf0912f2ea89282e0624de9e 100755 (executable)
@@ -702,6 +702,8 @@ static int rockchip_hdmiv2_config_phy(struct hdmi_dev *hdmi_dev)
                        clk_set_rate(hdmi_dev->pclk_phy, 148500000);
                else
                        clk_set_rate(hdmi_dev->pclk_phy, hdmi_dev->pixelclk);
+       } else if (hdmi_dev->soctype == HDMI_SOC_RK3399) {
+               clk_set_rate(hdmi_dev->pclk_phy, hdmi_dev->pixelclk);
        }
 
        hdmi_msk_reg(hdmi_dev, PHY_I2CM_DIV,
@@ -1722,6 +1724,7 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
        int word_length = 0, channel = 0, mclk_fs;
        unsigned int N = 0, CTS = 0;
        int rate = 0;
+       char design_id;
 
        HDMIDBG("%s\n", __func__);
 
@@ -1869,7 +1872,11 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
                hdmi_msk_reg(hdmi_dev, AUD_CONF0,
                             m_SW_AUD_FIFO_RST, v_SW_AUD_FIFO_RST(1));
                hdmi_writel(hdmi_dev, MC_SWRSTZREQ, 0xF7);
-               hdmi_writel(hdmi_dev, AUD_CONF2, 0x0);
+               design_id = hdmi_readl(hdmi_dev, DESIGN_ID);
+               if (design_id >= 0x21)
+                       hdmi_writel(hdmi_dev, AUD_CONF2, 0x4);
+               else
+                       hdmi_writel(hdmi_dev, AUD_CONF2, 0x0);
                usleep_range(90, 100);
                if (channel == I2S_CHANNEL_7_8) {
                        HDMIDBG("hbr mode.\n");
@@ -1881,7 +1888,10 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
                        hdmi_writel(hdmi_dev, AUD_CONF2, 0x2);
                        word_length = I2S_24BIT_SAMPLE;
                } else {
-                       hdmi_writel(hdmi_dev, AUD_CONF2, 0x0);
+                       if (design_id >= 0x21)
+                               hdmi_writel(hdmi_dev, AUD_CONF2, 0x4);
+                       else
+                               hdmi_writel(hdmi_dev, AUD_CONF2, 0x0);
                }
                hdmi_msk_reg(hdmi_dev, AUD_CONF0,
                             m_I2S_SEL | m_I2S_IN_EN,