rockchip: video: rk3399: add HDMI TX support on the RK3399
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>
Wed, 31 May 2017 15:59:34 +0000 (17:59 +0200)
committerSimon Glass <sjg@chromium.org>
Thu, 8 Jun 2017 03:30:50 +0000 (21:30 -0600)
This commit enables the RK3399 HDMI TX, which is very similar to the
one found on the RK3288.  As requested by Simon, this splits the HDMI
driver into a SOC-specific portion (rk3399_hdmi.c, rk3288_hdmi.c) and
a common portion (rk_hdmi.c).

Note that the I2C communication for reading the EDID works well with
the default settings, but does not with the alternate settings used on
the RK3288... this configuration aspect is reflected by the driverdata
for the RK3399 driver.

Having some sort of DTS-based configuration for the regulator
dependencies would be nice for the future, but for now we simply use
lists of regulator names (also via driverdata) that we probe.

Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
arch/arm/include/asm/arch-rockchip/grf_rk3399.h
drivers/video/rockchip/Makefile
drivers/video/rockchip/rk3399_hdmi.c [new file with mode: 0644]

index eda99560ed3039c8769e9f68ab6ef0b1c56b6931..8d21eb7bee7230a45d122a9916e977a665ac7ea0 100644 (file)
@@ -534,6 +534,9 @@ enum {
        GRF_DSI0_VOP_SEL_MASK   = 1 << GRF_DSI0_VOP_SEL_SHIFT,
        GRF_DSI0_VOP_SEL_B      = 0,
        GRF_DSI0_VOP_SEL_L      = 1,
+       GRF_RK3399_HDMI_VOP_SEL_MASK = 1 << 6,
+       GRF_RK3399_HDMI_VOP_SEL_B = 0 << 6,
+       GRF_RK3399_HDMI_VOP_SEL_L = 1 << 6,
 
        /* GRF_SOC_CON22 */
        GRF_DPHY_TX0_RXMODE_SHIFT = 0,
index 65d0ed64b8f76ac95c13d09424fecbd4a92f8317..872dc0f6534a67549f7555a4ff8612b9ef6097bd 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
 obj-hdmi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_hdmi.o
+obj-hdmi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_hdmi.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o $(obj-hdmi-y)
 obj-$(CONFIG_DISPLAY_ROCKCHIP_MIPI) += rk_mipi.o
 endif
diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
new file mode 100644 (file)
index 0000000..b1e5097
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <dw_hdmi.h>
+#include <edid.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/grf_rk3399.h>
+#include <power/regulator.h>
+#include "rk_hdmi.h"
+
+static int rk3399_hdmi_enable(struct udevice *dev, int panel_bpp,
+                             const struct display_timing *edid)
+{
+       struct rk_hdmi_priv *priv = dev_get_priv(dev);
+       struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
+       int vop_id = uc_plat->source_id;
+       struct rk3399_grf_regs *grf = priv->grf;
+
+       /* select the hdmi encoder input data from our source_id */
+       rk_clrsetreg(&grf->soc_con20, GRF_RK3399_HDMI_VOP_SEL_MASK,
+                    (vop_id == 1) ? GRF_RK3399_HDMI_VOP_SEL_L : 0);
+
+       return dw_hdmi_enable(&priv->hdmi, edid);
+}
+
+static int rk3399_hdmi_ofdata_to_platdata(struct udevice *dev)
+{
+       struct rk_hdmi_priv *priv = dev_get_priv(dev);
+       struct dw_hdmi *hdmi = &priv->hdmi;
+
+       hdmi->i2c_clk_high = 0x7a;
+       hdmi->i2c_clk_low = 0x8d;
+
+       return rk_hdmi_ofdata_to_platdata(dev);
+}
+
+static const char * const rk3399_regulator_names[] = {
+       "vcc1v8_hdmi",
+       "vcc0v9_hdmi"
+};
+
+static int rk3399_hdmi_probe(struct udevice *dev)
+{
+       /* Enable regulators required for HDMI */
+       rk_hdmi_probe_regulators(dev, rk3399_regulator_names,
+                                ARRAY_SIZE(rk3399_regulator_names));
+
+       return rk_hdmi_probe(dev);
+}
+
+static const struct dm_display_ops rk3399_hdmi_ops = {
+       .read_edid = rk_hdmi_read_edid,
+       .enable = rk3399_hdmi_enable,
+};
+
+static const struct udevice_id rk3399_hdmi_ids[] = {
+       { .compatible = "rockchip,rk3399-dw-hdmi" },
+       { }
+};
+
+U_BOOT_DRIVER(rk3399_hdmi_rockchip) = {
+       .name = "rk3399_hdmi_rockchip",
+       .id = UCLASS_DISPLAY,
+       .of_match = rk3399_hdmi_ids,
+       .ops = &rk3399_hdmi_ops,
+       .ofdata_to_platdata = rk3399_hdmi_ofdata_to_platdata,
+       .probe = rk3399_hdmi_probe,
+       .priv_auto_alloc_size = sizeof(struct rk_hdmi_priv),
+};