diff options
Diffstat (limited to 'drivers/video/rockchip/rk_edp.c')
-rw-r--r-- | drivers/video/rockchip/rk_edp.c | 103 |
1 files changed, 85 insertions, 18 deletions
diff --git a/drivers/video/rockchip/rk_edp.c b/drivers/video/rockchip/rk_edp.c index 0be60e169e..0ddf5e02d6 100644 --- a/drivers/video/rockchip/rk_edp.c +++ b/drivers/video/rockchip/rk_edp.c @@ -8,20 +8,21 @@ #include <clk.h> #include <display.h> #include <dm.h> +#include <dm/device_compat.h> #include <edid.h> #include <log.h> #include <malloc.h> #include <panel.h> #include <regmap.h> +#include <reset.h> #include <syscon.h> #include <asm/gpio.h> #include <asm/io.h> #include <asm/arch-rockchip/clock.h> +#include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/edp_rk3288.h> #include <asm/arch-rockchip/grf_rk3288.h> -#include <asm/arch-rockchip/hardware.h> -#include <dt-bindings/clock/rk3288-cru.h> -#include <linux/delay.h> +#include <asm/arch-rockchip/grf_rk3399.h> #define MAX_CR_LOOP 5 #define MAX_EQ_LOOP 5 @@ -37,18 +38,42 @@ static const char * const pre_emph_names[] = { #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 #define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 +#define RK3288_GRF_SOC_CON6 0x025c +#define RK3288_GRF_SOC_CON12 0x0274 +#define RK3399_GRF_SOC_CON20 0x6250 +#define RK3399_GRF_SOC_CON25 0x6264 + +enum rockchip_dp_types { + RK3288_DP = 0, + RK3399_EDP +}; + +struct rockchip_dp_data { + unsigned long reg_vop_big_little; + unsigned long reg_vop_big_little_sel; + unsigned long reg_ref_clk_sel; + unsigned long ref_clk_sel_bit; + enum rockchip_dp_types chip_type; +}; + struct rk_edp_priv { struct rk3288_edp *regs; - struct rk3288_grf *grf; + void *grf; struct udevice *panel; struct link_train link_train; u8 train_set[4]; }; -static void rk_edp_init_refclk(struct rk3288_edp *regs) +static void rk_edp_init_refclk(struct rk3288_edp *regs, enum rockchip_dp_types chip_type) { writel(SEL_24M, ®s->analog_ctl_2); - writel(REF_CLK_24M, ®s->pll_reg_1); + u32 reg; + + reg = REF_CLK_24M; + if (chip_type == RK3288_DP) + reg ^= REF_CLK_MASK; + writel(reg, ®s->pll_reg_1); + writel(LDO_OUTPUT_V_SEL_145 | KVCO_DEFALUT | CHG_PUMP_CUR_SEL_5US | V2L_CUR_SEL_1MA, ®s->pll_reg_2); @@ -1029,6 +1054,9 @@ static int rk_edp_probe(struct udevice *dev) struct display_plat *uc_plat = dev_get_uclass_plat(dev); struct rk_edp_priv *priv = dev_get_priv(dev); struct rk3288_edp *regs = priv->regs; + struct rockchip_dp_data *edp_data = (struct rockchip_dp_data *)dev_get_driver_data(dev); + struct reset_ctl dp_rst; + struct clk clk; int ret; @@ -1040,19 +1068,39 @@ static int rk_edp_probe(struct udevice *dev) return ret; } - int vop_id = uc_plat->source_id; - debug("%s, uc_plat=%p, vop_id=%u\n", __func__, uc_plat, vop_id); + ret = reset_get_by_name(dev, "dp", &dp_rst); + if (ret) { + dev_err(dev, "failed to get dp reset (ret=%d)\n", ret); + return ret; + } - ret = clk_get_by_index(dev, 1, &clk); - if (ret >= 0) { - ret = clk_set_rate(&clk, 0); - clk_free(&clk); + ret = reset_assert(&dp_rst); + if (ret) { + dev_err(dev, "failed to assert dp reset (ret=%d)\n", ret); + return ret; } + udelay(20); + + ret = reset_deassert(&dp_rst); if (ret) { - debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret); + dev_err(dev, "failed to deassert dp reset (ret=%d)\n", ret); return ret; } + int vop_id = uc_plat->source_id; + debug("%s, uc_plat=%p, vop_id=%u\n", __func__, uc_plat, vop_id); + + if (edp_data->chip_type == RK3288_DP) { + ret = clk_get_by_index(dev, 1, &clk); + if (ret >= 0) { + ret = clk_set_rate(&clk, 0); + clk_free(&clk); + } + if (ret) { + debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret); + return ret; + } + } ret = clk_get_by_index(uc_plat->src_dev, 0, &clk); if (ret >= 0) { ret = clk_set_rate(&clk, 192000000); @@ -1065,15 +1113,17 @@ static int rk_edp_probe(struct udevice *dev) } /* grf_edp_ref_clk_sel: from internal 24MHz or 27MHz clock */ - rk_setreg(&priv->grf->soc_con12, 1 << 4); + rk_setreg(priv->grf + edp_data->reg_ref_clk_sel, + edp_data->ref_clk_sel_bit); /* select epd signal from vop0 or vop1 */ - rk_clrsetreg(&priv->grf->soc_con6, (1 << 5), - (vop_id == 1) ? (1 << 5) : (0 << 5)); + rk_clrsetreg(priv->grf + edp_data->reg_vop_big_little, + edp_data->reg_vop_big_little_sel, + (vop_id == 1) ? edp_data->reg_vop_big_little_sel : 0); rockchip_edp_wait_hpd(priv); - rk_edp_init_refclk(regs); + rk_edp_init_refclk(regs, edp_data->chip_type); rk_edp_init_interrupt(regs); rk_edp_enable_sw_function(regs); ret = rk_edp_init_analog_func(regs); @@ -1089,8 +1139,25 @@ static const struct dm_display_ops dp_rockchip_ops = { .enable = rk_edp_enable, }; +static const struct rockchip_dp_data rk3399_edp = { + .reg_vop_big_little = RK3399_GRF_SOC_CON20, + .reg_vop_big_little_sel = BIT(5), + .reg_ref_clk_sel = RK3399_GRF_SOC_CON25, + .ref_clk_sel_bit = BIT(11), + .chip_type = RK3399_EDP, +}; + +static const struct rockchip_dp_data rk3288_dp = { + .reg_vop_big_little = RK3288_GRF_SOC_CON6, + .reg_vop_big_little_sel = BIT(5), + .reg_ref_clk_sel = RK3288_GRF_SOC_CON12, + .ref_clk_sel_bit = BIT(4), + .chip_type = RK3288_DP, +}; + static const struct udevice_id rockchip_dp_ids[] = { - { .compatible = "rockchip,rk3288-edp" }, + { .compatible = "rockchip,rk3288-edp", .data = (ulong)&rk3288_dp }, + { .compatible = "rockchip,rk3399-edp", .data = (ulong)&rk3399_edp }, { } }; |