summaryrefslogtreecommitdiffstats
path: root/drivers/video/rockchip/rk_edp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/rockchip/rk_edp.c')
-rw-r--r--drivers/video/rockchip/rk_edp.c103
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, &regs->analog_ctl_2);
- writel(REF_CLK_24M, &regs->pll_reg_1);
+ u32 reg;
+
+ reg = REF_CLK_24M;
+ if (chip_type == RK3288_DP)
+ reg ^= REF_CLK_MASK;
+ writel(reg, &regs->pll_reg_1);
+
writel(LDO_OUTPUT_V_SEL_145 | KVCO_DEFALUT | CHG_PUMP_CUR_SEL_5US |
V2L_CUR_SEL_1MA, &regs->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 },
{ }
};