video: rockchip: tve: support rk3228
authorShen Zhenyi <szy@rock-chips.com>
Mon, 19 Oct 2015 03:21:25 +0000 (11:21 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 20 Oct 2015 03:02:25 +0000 (11:02 +0800)
Change-Id: I7046f5b42de442c8bf7946a537d3e26922882d1d
Signed-off-by: Shen Zhenyi <szy@rock-chips.com>
drivers/video/rockchip/tve/rk3036/rk3036_tve.c
drivers/video/rockchip/tve/rk3036/rk3036_tve.h

index 6551332c6642c8b65f54152c58f7f20398908c93..19a5b3b4da629ae8d115629bdd27123d917992dd 100755 (executable)
  *
  *
  */
-#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/display-sys.h>
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/module.h>
 #include <linux/rk_fb.h>
-#include <linux/display-sys.h>
 #include <linux/rockchip/grf.h>
 #include <linux/rockchip/iomap.h>
 #include "rk3036_tve.h"
 
+
 static const struct fb_videomode rk3036_cvbs_mode[] = {
        /*name          refresh xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw                    polariry                                PorI            flag*/
 /*     {"NTSC",        60,     720,    480,    27000000,       57,     19,     19,     0,      62,     3,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   FB_VMODE_INTERLACED,    0},
        {"PAL",         50,     720,    576,    27000000,       69,     12,     19,     2,      63,     3,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   FB_VMODE_INTERLACED,    0},
 */     {"NTSC",        60,     720,    480,    27000000,       43,     33,     19,     0,      62,     3,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   FB_VMODE_INTERLACED,    0},
-       {"PAL",         50,     720,    576,    27000000,       52,     29,     19,     2,      63,     3,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   FB_VMODE_INTERLACED,    0},
+       {"PAL",         50,     720,    576,    27000000,       48,     33,     19,     2,      63,     3,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   FB_VMODE_INTERLACED,    0},
 };
 
 static struct rk3036_tve *rk3036_tve;
@@ -36,6 +39,9 @@ static int cvbsformat = -1;
 #define tve_writel(offset, v)  writel_relaxed(v, rk3036_tve->regbase + offset)
 #define tve_readl(offset)      readl_relaxed(rk3036_tve->regbase + offset)
 
+#define tve_dac_writel(offset, v)   writel_relaxed(v, rk3036_tve->vdacbase + offset)
+#define tve_dac_readl(offset)  readl_relaxed(rk3036_tve->vdacbase + offset)
+
 #ifdef DEBUG
 #define TVEDBG(format, ...) \
                dev_info(rk3036_tve->dev,\
@@ -59,6 +65,8 @@ static void dac_enable(bool enable)
                } else if (rk3036_tve->soctype == SOC_RK3036) {
                        val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(0x3e);
                        grfreg = RK3036_GRF_SOC_CON3;
+               } else if (rk3036_tve->soctype == SOC_RK3228) {
+                       val = 0xb0;
                }
        } else {
                mask = m_VBG_EN | m_DAC_EN;
@@ -67,9 +75,22 @@ static void dac_enable(bool enable)
                        grfreg = RK312X_GRF_TVE_CON;
                else if (rk3036_tve->soctype == SOC_RK3036)
                        grfreg = RK3036_GRF_SOC_CON3;
+               else if (rk3036_tve->soctype == SOC_RK3228)
+                       val = v_CUR_REG(0xb) | m_DR_PWR_DOWN | m_BG_PWR_DOWN;
        }
        if (grfreg)
                grf_writel(grfreg, (mask << 16) | val);
+       else if (rk3036_tve->vdacbase)
+               tve_dac_writel(VDAC_VDAC1, val);
+}
+
+static void rk3228_dac_init(void)
+{
+       /*tve_dac_writel(VDAC_VDAC0, 0x0);*/
+       tve_dac_writel(VDAC_VDAC1, v_CUR_REG(0xb) |
+                                  m_DR_PWR_DOWN | m_BG_PWR_DOWN);
+       tve_dac_writel(VDAC_VDAC2, v_CUR_CTR(0x39));
+       tve_dac_writel(VDAC_VDAC3, v_CAB_EN(0));
 }
 
 static void tve_set_mode(int mode)
@@ -77,9 +98,11 @@ static void tve_set_mode(int mode)
        TVEDBG("%s mode %d\n", __func__, mode);
        if (cvbsformat >= 0)
                return;
-       tve_writel(TV_RESET, v_RESET(1));
-       usleep_range(100, 100);
-       tve_writel(TV_RESET, v_RESET(0));
+       if (rk3036_tve->soctype != SOC_RK3228) {
+               tve_writel(TV_RESET, v_RESET(1));
+               usleep_range(100, 110);
+               tve_writel(TV_RESET, v_RESET(0));
+       }
        if (rk3036_tve->inputformat == INPUT_FORMAT_RGB)
                tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
                           v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
@@ -88,10 +111,15 @@ static void tve_set_mode(int mode)
                tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
                           v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
                           v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(3));
-
-       tve_writel(TV_LUMA_FILTER0, 0x02ff0000);
-       tve_writel(TV_LUMA_FILTER1, 0xF40202fd);
-       tve_writel(TV_LUMA_FILTER2, 0xF332d919);
+       if (rk3036_tve->soctype == SOC_RK3228) {
+               tve_writel(TV_LUMA_FILTER0, 0x02ff0001);
+               tve_writel(TV_LUMA_FILTER1, 0xF40202fe);
+               tve_writel(TV_LUMA_FILTER2, 0xF332d910);
+       } else {
+               tve_writel(TV_LUMA_FILTER0, 0x02ff0000);
+               tve_writel(TV_LUMA_FILTER1, 0xF40202fd);
+               tve_writel(TV_LUMA_FILTER2, 0xF332d919);
+       }
 
        if (mode == TVOUT_CVBS_NTSC) {
                tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) |
@@ -100,10 +128,10 @@ static void tve_set_mode(int mode)
                tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_NTSC) |
                        v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
                tve_writel(TV_SATURATION, 0x0042543C);
-               if(rk3036_tve->test_mode)
-               tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300);
+               if (rk3036_tve->test_mode)
+                       tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300);
                else
-               tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007900);
+                       tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007900);
 
                tve_writel(TV_FREQ_SC,  0x21F07BD7);
                tve_writel(TV_SYNC_TIMING, 0x00C07a81);
@@ -119,10 +147,13 @@ static void tve_set_mode(int mode)
                        v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
                if (rk3036_tve->soctype == SOC_RK312X) {
                        tve_writel(TV_SATURATION, /*0x00325c40*/ 0x002b4d3c);
-                       if(rk3036_tve->test_mode)
-                       tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008a0a);
+                       if (rk3036_tve->test_mode)
+                               tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008a0a);
                        else
-                       tve_writel(TV_BRIGHTNESS_CONTRAST, 0x0000770a);
+                               tve_writel(TV_BRIGHTNESS_CONTRAST, 0x0000770a);
+               } else if (rk3036_tve->soctype == SOC_RK3228) {
+                       tve_writel(TV_SATURATION, 0x00386346);
+                       tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00009000);
                } else {
                        tve_writel(TV_SATURATION, /*0x00325c40*/ 0x00386346);
                        tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008b00);
@@ -136,7 +167,7 @@ static void tve_set_mode(int mode)
                if (rk3036_tve->soctype == SOC_RK312X) {
                        tve_writel(TV_ADJ_TIMING, (0xa << 28) |
                                        0x06c00800 | 0x80);
-                       usleep_range(100, 100);
+                       usleep_range(100, 150);
                        tve_writel(TV_ADJ_TIMING, (0xa << 28) |
                                        0x06c00800 | 0x80);
                        tve_writel(TV_ACT_TIMING, 0x0694011D |
@@ -285,6 +316,8 @@ tve_fb_event_notify(struct notifier_block *self,
                                if (rk3036_tve->enable) {
                                        tve_switch_fb(rk3036_tve->mode, 0);
                                        dac_enable(false);
+                                       if (rk3036_tve->soctype == SOC_RK3228)
+                                               clk_disable_unprepare(rk3036_tve->dac_clk);
                                }
                        }
                        break;
@@ -294,6 +327,10 @@ tve_fb_event_notify(struct notifier_block *self,
                case FB_BLANK_UNBLANK:
                        TVEDBG("resume tve\n");
                        if (rk3036_tve->suspend) {
+                               if (rk3036_tve->soctype == SOC_RK3228) {
+                                       clk_prepare_enable(rk3036_tve->dac_clk);
+                                       rk3228_dac_init();
+                               }
                                rk3036_tve->suspend = 0;
                                if (rk3036_tve->enable) {
                                        tve_switch_fb(rk3036_tve->mode, 1);
@@ -341,6 +378,7 @@ static struct rk_display_driver display_cvbs = {
 static const struct of_device_id rk3036_tve_dt_ids[] = {
        {.compatible = "rockchip,rk3036-tve",},
        {.compatible = "rockchip,rk312x-tve",},
+       {.compatible = "rockchip,rk3228-tve",},
        {}
 };
 #endif
@@ -359,7 +397,6 @@ static int __init bootloader_tve_setup(char *str)
 
 early_param("tve.format", bootloader_tve_setup);
 
-
 static int rk3036_tve_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -395,6 +432,9 @@ static int rk3036_tve_probe(struct platform_device *pdev)
        } else if (!strcmp(match->compatible, "rockchip,rk312x-tve")) {
                rk3036_tve->soctype = SOC_RK312X;
                rk3036_tve->inputformat = INPUT_FORMAT_YUV;
+       } else if (!strcmp(match->compatible, "rockchip,rk3228-tve")) {
+               rk3036_tve->soctype = SOC_RK3228;
+               rk3036_tve->inputformat = INPUT_FORMAT_YUV;
        } else {
                dev_err(&pdev->dev, "It is not a valid tv encoder!");
                kfree(rk3036_tve);
@@ -412,7 +452,27 @@ static int rk3036_tve_probe(struct platform_device *pdev)
                        "rk3036 tv encoder device map registers failed!");
                return PTR_ERR(rk3036_tve->regbase);
        }
-
+       if (rk3036_tve->soctype == SOC_RK3228) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               rk3036_tve->len = resource_size(res);
+               rk3036_tve->vdacbase = devm_ioremap(rk3036_tve->dev,
+                                                   res->start,
+                                                   rk3036_tve->len);
+               if (IS_ERR(rk3036_tve->vdacbase)) {
+                       dev_err(&pdev->dev,
+                               "rk3036 tv encoder device dac map registers failed!");
+                       return PTR_ERR(rk3036_tve->vdacbase);
+               }
+               rk3036_tve->dac_clk =
+                               devm_clk_get(rk3036_tve->dev, "pclk_vdac");
+               if (IS_ERR(rk3036_tve->dac_clk)) {
+                       dev_err(&pdev->dev,
+                               "Unable to get vdac_clk\n");
+                       return PTR_ERR(rk3036_tve->dac_clk);
+               }
+               clk_prepare_enable(rk3036_tve->dac_clk);
+               rk3228_dac_init();
+       }
        INIT_LIST_HEAD(&(rk3036_tve->modelist));
        for (i = 0; i < ARRAY_SIZE(rk3036_cvbs_mode); i++)
                fb_add_videomode(&rk3036_cvbs_mode[i], &(rk3036_tve->modelist));
index d8940c7923cabdc764f978fedf5365170130c621..6b902bf16773ade851118015a7a29a6de748cb4e 100644 (file)
 #define m_DAC_GAIN             (0x3f << 7)
 #define v_DAC_GAIN(x)          ((x & 0x3f) << 7)
 
+#define VDAC_VDAC0             (0x00)
+       #define m_RST_ANA               (1 << 7)
+       #define m_RST_DIG               (1 << 6)
+
+       #define v_RST_ANA(x)            ((x & 1) << 7)
+       #define v_RST_DIG(x)            ((x & 1) << 6)
+#define VDAC_VDAC1             (0x280)
+       #define m_CUR_REG               (0xf << 4)
+       #define m_DR_PWR_DOWN           (1 << 1)
+       #define m_BG_PWR_DOWN           (1 << 0)
+
+       #define v_CUR_REG(x)            ((x & 0xf) << 4)
+       #define v_DR_PWR_DOWN(x)        ((x & 1) << 1)
+       #define v_BG_PWR_DOWN(x)        ((x & 1) << 0)
+#define VDAC_VDAC2             (0x284)
+       #define m_CUR_CTR               (0X3f)
+
+       #define v_CUR_CTR(x)            ((x & 0X3f))
+#define VDAC_VDAC3             (0x288)
+       #define m_CAB_EN                (1 << 5)
+       #define m_CAB_REF               (1 << 4)
+       #define m_CAB_FLAG              (1 << 0)
+
+       #define v_CAB_EN(x)             ((x & 1) << 5)
+       #define v_CAB_REF(x)            ((x & 1) << 4)
+       #define v_CAB_FLAG(x)           ((x & 1) << 0)
+
 enum {
        TVOUT_CVBS_NTSC = 0,
        TVOUT_CVBS_PAL,
@@ -90,7 +117,8 @@ enum {
 
 enum {
        SOC_RK3036 = 0,
-       SOC_RK312X
+       SOC_RK312X,
+       SOC_RK3228
 };
 
 #define TVOUT_DEAULT TVOUT_CVBS_PAL
@@ -103,6 +131,8 @@ enum {
 struct rk3036_tve {
        struct device                   *dev;
        void __iomem                    *regbase;
+       void __iomem                    *vdacbase;
+       struct clk                      *dac_clk;
        u32                             reg_phy_base;
        u32                             len;
        int                             soctype;
@@ -117,4 +147,5 @@ struct rk3036_tve {
        int saturation;
 };
 
-#endif
\ No newline at end of file
+#endif
+