Hi Philipp, Dne petek, 28. april 2017 ob 17:53:11 CEST je Philipp Tomsich napisal(a): > This commit enables the RK3399 HDMI TX, which is very similar to the > one found on the RK3288. The differences between the two SoCs (mainly > the input VOP selection) is abstracted away through the driverdata. > > 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... so this configuration aspect also is part of the > driverdata. > > 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.toms...@theobroma-systems.com> > --- > > arch/arm/include/asm/arch-rockchip/grf_rk3399.h | 5 + > drivers/video/rockchip/rk_hdmi.c | 165 > +++++++++++++++++++----- 2 files changed, 135 insertions(+), 35 > deletions(-) > > diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h > b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h index 22d8d97..ddd558e > 100644 > --- a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h > +++ b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h > @@ -462,6 +462,11 @@ enum { > GRF_UART_DBG_SEL_MASK = 3 << GRF_UART_DBG_SEL_SHIFT, > GRF_UART_DBG_SEL_C = 2, > > + /* GRF_SOC_CON20 */ > + GRF_RK3399_HDMI_VOP_SEL_MASK = 1 << 6, > + GRF_RK3399_HDMI_VOP_SEL_B = 0 << 6, > + GRF_RK3399_HDMI_VOP_SEL_L = 1 << 6, > + > /* PMUGRF_GPIO0A_IOMUX */ > PMUGRF_GPIO0A6_SEL_SHIFT = 12, > PMUGRF_GPIO0A6_SEL_MASK = 3 << PMUGRF_GPIO0A6_SEL_SHIFT, > diff --git a/drivers/video/rockchip/rk_hdmi.c > b/drivers/video/rockchip/rk_hdmi.c index db07588..ea92551 100644 > --- a/drivers/video/rockchip/rk_hdmi.c > +++ b/drivers/video/rockchip/rk_hdmi.c > @@ -1,10 +1,13 @@ > /* > + * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH > * Copyright (c) 2015 Google, Inc > * Copyright 2014 Rockchip Inc. > * > * SPDX-License-Identifier: GPL-2.0+ > */ > > +#define DEBUG > +
That shouldn't be in final version. > #include <common.h> > #include <clk.h> > #include <display.h> > @@ -16,12 +19,25 @@ > #include <asm/gpio.h> > #include <asm/io.h> > #include <asm/arch/clock.h> > +#include <asm/arch/hardware.h> > #include <asm/arch/grf_rk3288.h> > +#include <asm/arch/grf_rk3399.h> > #include <power/regulator.h> > > struct rk_hdmi_priv { > struct dw_hdmi hdmi; > - struct rk3288_grf *grf; > + void *grf; > +}; > + > +struct rkhdmi_driverdata { > + /* configuration */ > + u8 i2c_clk_high; > + u8 i2c_clk_low; > + const char * const *regulator_names; > + u32 regulator_names_cnt; > + /* setters/getters */ > + int (*set_input_vop)(struct udevice *dev); > + int (*clk_config)(struct udevice *dev); > }; > > static const struct hdmi_phy_config rockchip_phy_config[] = { > @@ -65,6 +81,60 @@ static const struct hdmi_mpll_config rockchip_mpll_cfg[] > = { } > }; > > +static int rk3288_set_input_vop(struct udevice *dev) > +{ > + 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 rk3288_grf *grf = priv->grf; > + > + /* hdmi source select hdmi controller */ > + rk_setreg(&grf->soc_con6, 1 << 15); > + > + /* hdmi data from vop id */ > + rk_clrsetreg(&grf->soc_con6, 1 << 4, (vop_id == 1) ? (1 << 4) : 0); > + > + return 0; > +} > + > +static int rk3399_set_input_vop(struct udevice *dev) > +{ > + 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; > + > + /* hdmi data from vop id */ > + rk_clrsetreg(&grf->soc_con20, GRF_RK3399_HDMI_VOP_SEL_MASK, > + (vop_id == 1) ? GRF_RK3399_HDMI_VOP_SEL_L : 0); > + > + return 0; > +} > + > +static int rk3288_clk_config(struct udevice *dev) > +{ > + struct display_plat *uc_plat = dev_get_uclass_platdata(dev); > + struct clk clk; > + int ret; > + > + /* > + * Configure the maximum clock to permit whatever resolution the > + * monitor wants > + */ > + ret = clk_get_by_index(uc_plat->src_dev, 0, &clk); > + if (ret >= 0) { > + ret = clk_set_rate(&clk, 384000000); > + clk_free(&clk); > + } > + if (ret < 0) { > + debug("%s: Failed to set clock in source device '%s': ret=%d\n", > + __func__, uc_plat->src_dev->name, ret); > + return ret; > + } > + > + return 0; > +} > + > static int rk_hdmi_read_edid(struct udevice *dev, u8 *buf, int buf_size) > { > struct rk_hdmi_priv *priv = dev_get_priv(dev); > @@ -83,20 +153,16 @@ static int rk_hdmi_enable(struct udevice *dev, int > panel_bpp, static int rk_hdmi_ofdata_to_platdata(struct udevice *dev) > { > struct rk_hdmi_priv *priv = dev_get_priv(dev); > + struct rkhdmi_driverdata *data = > + (struct rkhdmi_driverdata *)dev_get_driver_data(dev); > struct dw_hdmi *hdmi = &priv->hdmi; > > hdmi->ioaddr = (ulong)dev_get_addr(dev); > hdmi->mpll_cfg = rockchip_mpll_cfg; > hdmi->phy_cfg = rockchip_phy_config; > - hdmi->i2c_clk_high = 0x7a; > - hdmi->i2c_clk_low = 0x8d; > + hdmi->i2c_clk_high = data->i2c_clk_high; > + hdmi->i2c_clk_low = data->i2c_clk_low; > > - /* > - * TODO(s...@chromium.org): The above values don't work - these ones > - * work better, but generate lots of errors in the data. > - */ > - hdmi->i2c_clk_high = 0x0d; > - hdmi->i2c_clk_low = 0x0d; > hdmi->reg_io_width = 4; > hdmi->phy_set = dw_hdmi_phy_cfg; > > @@ -107,13 +173,15 @@ static int rk_hdmi_ofdata_to_platdata(struct udevice > *dev) > > static int rk_hdmi_probe(struct udevice *dev) > { > - struct display_plat *uc_plat = dev_get_uclass_platdata(dev); > + struct rkhdmi_driverdata *data = > + (struct rkhdmi_driverdata *)dev_get_driver_data(dev); > struct rk_hdmi_priv *priv = dev_get_priv(dev); > struct dw_hdmi *hdmi = &priv->hdmi; > struct udevice *reg; > struct clk clk; > + const char *regulator_name; > int ret; > - int vop_id = uc_plat->source_id; > + int i; > > ret = clk_get_by_index(dev, 0, &clk); > if (ret >= 0) { > @@ -125,33 +193,27 @@ static int rk_hdmi_probe(struct udevice *dev) > return ret; > } > > - /* > - * Configure the maximum clock to permit whatever resolution the > - * monitor wants > - */ > - ret = clk_get_by_index(uc_plat->src_dev, 0, &clk); > - if (ret >= 0) { > - ret = clk_set_rate(&clk, 384000000); > - clk_free(&clk); > - } > - if (ret < 0) { > - debug("%s: Failed to set clock in source device '%s': ret=%d\n", > - __func__, uc_plat->src_dev->name, ret); > - return ret; > + if (data->clk_config) { > + ret = data->clk_config(dev); > + if (ret < 0) > + return ret; > } > > - ret = regulator_get_by_platname("vcc50_hdmi", ®); > - if (!ret) > - ret = regulator_set_enable(reg, true); > - if (ret) > - debug("%s: Cannot set regulator vcc50_hdmi\n", __func__); > + for (i = 0; i < data->regulator_names_cnt; ++i) { > + regulator_name = data->regulator_names[i]; > + debug("%s: probing regulator '%s'\n", __func__, regulator_name); > > - /* hdmi source select hdmi controller */ > - rk_setreg(&priv->grf->soc_con6, 1 << 15); > + ret = regulator_autoset_by_name(regulator_name, ®); > + if (!ret) > + ret = regulator_set_enable(reg, true); > + } > > - /* hdmi data from vop id */ > - rk_clrsetreg(&priv->grf->soc_con6, 1 << 4, > - (vop_id == 1) ? (1 << 4) : 0); > + if (!data->set_input_vop) { > + debug("%s: data->set_input_vop not set\n", __func__); > + return -1; > + } > + > + data->set_input_vop(dev); > > ret = dw_hdmi_phy_wait_for_hpd(hdmi); > if (ret < 0) { > @@ -170,8 +232,41 @@ static const struct dm_display_ops rk_hdmi_ops = { > .enable = rk_hdmi_enable, > }; > > +static const char * const rk3288_regulator_names[] = { > + "vcc50_hdmi", > +}; > + > +static const struct rkhdmi_driverdata rk3288_driverdata = { > + /* > + * TODO(s...@chromium.org): The above values don't work - these ones > + * work better, but generate lots of errors in the data. > + */ Maybe you should rephrase the comment. In this form it doesn't make sense anymore. Regards, Jernej > + .i2c_clk_high = 0x0d, > + .i2c_clk_low = 0x0d, > + .regulator_names = rk3288_regulator_names, > + .regulator_names_cnt = ARRAY_SIZE(rk3288_regulator_names), > + .set_input_vop = rk3288_set_input_vop, > + .clk_config = rk3288_clk_config, > +}; > + > +static const char * const rk3399_regulator_names[] = { > + "vcc1v8_hdmi", > + "vcc0v9_hdmi" > +}; > + > +static const struct rkhdmi_driverdata rk3399_driverdata = { > + .i2c_clk_high = 0x7a, > + .i2c_clk_low = 0x8d, > + .regulator_names = rk3399_regulator_names, > + .regulator_names_cnt = ARRAY_SIZE(rk3399_regulator_names), > + .set_input_vop = rk3399_set_input_vop, > +}; > + > static const struct udevice_id rk_hdmi_ids[] = { > - { .compatible = "rockchip,rk3288-dw-hdmi" }, > + { .compatible = "rockchip,rk3288-dw-hdmi", > + .data = (ulong)&rk3288_driverdata }, > + { .compatible = "rockchip,rk3399-dw-hdmi", > + .data = (ulong)&rk3399_driverdata }, > { } > }; > > -- > 1.9.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot