From e659022b9319ed70cad99611619e980ed9112022 Mon Sep 17 00:00:00 2001 From: xuhuicong Date: Tue, 12 Apr 2016 09:16:30 +0800 Subject: [PATCH] video: rockchip: hdmi: support rk3399 hdmi 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 --- .../bindings/video/rockchip_hdmi.txt | 6 ++-- drivers/video/rockchip/hdmi/rockchip-hdmi.h | 1 + .../hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c | 28 +++++++++++++++++-- .../hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c | 14 ++++++++-- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/video/rockchip_hdmi.txt b/Documentation/devicetree/bindings/video/rockchip_hdmi.txt index 806527857ae2..67c9080063a3 100644 --- a/Documentation/devicetree/bindings/video/rockchip_hdmi.txt +++ b/Documentation/devicetree/bindings/video/rockchip_hdmi.txt @@ -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. diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi.h b/drivers/video/rockchip/hdmi/rockchip-hdmi.h index 953f054792b7..ec5dc21438e2 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi.h +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi.h @@ -377,6 +377,7 @@ enum { HDMI_SOC_RK3288, HDMI_SOC_RK3366, HDMI_SOC_RK3368, + HDMI_SOC_RK3399, }; /* HDMI Information */ diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c index 86cedf5f548c..2b04162fd02d 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c @@ -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; diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c index d39998d259c6..6c85f076528a 100755 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c @@ -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, -- 2.34.1