drm/rockchip: dw_hdmi: add RK3399 HDMI support
authorMark Yao <mark.yao@rock-chips.com>
Thu, 22 Jun 2017 07:17:24 +0000 (15:17 +0800)
committerMark Yao <mark.yao@rock-chips.com>
Fri, 23 Jun 2017 00:52:03 +0000 (08:52 +0800)
RK3399 and RK3288 shared the same HDMI IP controller, only some light
difference with GRF configure.

Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
Acked-by: Rob Herring <robh@kernel.org>
Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c

index 046076c6b2775b8124da53ce4647094fe7e3c96c..7039a15b0d0498e770131711ec03c0e7c08e359c 100644 (file)
@@ -11,7 +11,9 @@ following device-specific properties.
 
 Required properties:
 
-- compatible: Shall contain "rockchip,rk3288-dw-hdmi".
+- compatible: should be one of the following:
+               "rockchip,rk3288-dw-hdmi"
+               "rockchip,rk3399-dw-hdmi"
 - reg: See dw_hdmi.txt.
 - reg-io-width: See dw_hdmi.txt. Shall be 4.
 - interrupts: HDMI interrupt number
index f8208489724e02d7953660b27a2247a06a817996..e7bab14134dae548f3b2bc725e180b549b6af7dd 100644 (file)
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_vop.h"
 
-#define GRF_SOC_CON6                    0x025c
-#define HDMI_SEL_VOP_LIT                (1 << 4)
+#define RK3288_GRF_SOC_CON6            0x025C
+#define RK3288_HDMI_LCDC_SEL           BIT(4)
+#define RK3399_GRF_SOC_CON20           0x6250
+#define RK3399_HDMI_LCDC_SEL           BIT(6)
+
+#define HIWORD_UPDATE(val, mask)       (val | (mask) << 16)
+
+/**
+ * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips
+ * @lcdsel_grf_reg: grf register offset of lcdc select
+ * @lcdsel_big: reg value of selecting vop big for HDMI
+ * @lcdsel_lit: reg value of selecting vop little for HDMI
+ */
+struct rockchip_hdmi_chip_data {
+       u32     lcdsel_grf_reg;
+       u32     lcdsel_big;
+       u32     lcdsel_lit;
+};
 
 struct rockchip_hdmi {
        struct device *dev;
        struct regmap *regmap;
        struct drm_encoder encoder;
+       const struct rockchip_hdmi_chip_data *chip_data;
 };
 
 #define to_rockchip_hdmi(x)    container_of(x, struct rockchip_hdmi, x)
@@ -198,17 +215,20 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
 {
        struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
        u32 val;
-       int mux;
+       int ret;
 
-       mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
-       if (mux)
-               val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
+       ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
+       if (ret)
+               val = hdmi->chip_data->lcdsel_lit;
        else
-               val = HDMI_SEL_VOP_LIT << 16;
+               val = hdmi->chip_data->lcdsel_big;
+
+       ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val);
+       if (ret != 0)
+               dev_err(hdmi->dev, "Could not write to GRF: %d\n", ret);
 
-       regmap_write(hdmi->regmap, GRF_SOC_CON6, val);
        dev_dbg(hdmi->dev, "vop %s output to hdmi\n",
-               (mux) ? "LIT" : "BIG");
+               ret ? "LIT" : "BIG");
 }
 
 static int
@@ -232,16 +252,40 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun
        .atomic_check = dw_hdmi_rockchip_encoder_atomic_check,
 };
 
-static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
+static struct rockchip_hdmi_chip_data rk3288_chip_data = {
+       .lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
+       .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL),
+       .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL),
+};
+
+static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
+       .mode_valid = dw_hdmi_rockchip_mode_valid,
+       .mpll_cfg   = rockchip_mpll_cfg,
+       .cur_ctr    = rockchip_cur_ctr,
+       .phy_config = rockchip_phy_config,
+       .phy_data = &rk3288_chip_data,
+};
+
+static struct rockchip_hdmi_chip_data rk3399_chip_data = {
+       .lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
+       .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL),
+       .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL),
+};
+
+static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
        .mode_valid = dw_hdmi_rockchip_mode_valid,
        .mpll_cfg   = rockchip_mpll_cfg,
        .cur_ctr    = rockchip_cur_ctr,
        .phy_config = rockchip_phy_config,
+       .phy_data = &rk3399_chip_data,
 };
 
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
        { .compatible = "rockchip,rk3288-dw-hdmi",
-         .data = &rockchip_hdmi_drv_data
+         .data = &rk3288_hdmi_drv_data
+       },
+       { .compatible = "rockchip,rk3399-dw-hdmi",
+         .data = &rk3399_hdmi_drv_data
        },
        {},
 };
@@ -268,6 +312,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
        match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
        plat_data = match->data;
        hdmi->dev = &pdev->dev;
+       hdmi->chip_data = plat_data->phy_data;
        encoder = &hdmi->encoder;
 
        encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);