Files

494 lines
16 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <[email protected]>
Date: Sun, 30 Jun 2024 17:18:22 +0200
Subject: add rk3228 support to inno hdmi driver
---
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 379 ++++++++++
1 file changed, 379 insertions(+)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 111111111111..222222222222 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -19,6 +19,110 @@
#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
+/*
+ * ---- Registers for RK322x
+ */
+/* REG: 0x00 */
+#define RK3228_PRE_PLL_REFCLK_SEL_MASK BIT(0)
+#define RK3228_PRE_PLL_REFCLK_SEL_PCLK BIT(0)
+#define RK3228_PRE_PLL_REFCLK_SEL_OSCCLK 0
+/* REG: 0x01 */
+#define RK3228_BYPASS_RXSENSE_EN BIT(2)
+#define RK3228_BYPASS_PWRON_EN BIT(1)
+#define RK3228_BYPASS_PLLPD_EN BIT(0)
+/* REG: 0x02 */
+#define RK3228_INT_POL_HIGH BIT(7)
+#define RK3228_BYPASS_PDATA_EN BIT(4)
+#define RK3328_PDATA_EN BIT(0)
+#define RK3228_PDATA_EN_DISABLE BIT(0)
+/* REG: 0x03 */
+#define RK3228_BYPASS_AUTO_TERM_RES_CAL BIT(7)
+#define RK3228_AUDO_TERM_RES_CAL_SPEED_14_8(x) UPDATE(x, 6, 0)
+/* REG: 0x04 */
+#define RK3228_AUDO_TERM_RES_CAL_SPEED_7_0(x) UPDATE(x, 7, 0)
+/* REG: 0xaa */
+#define RK3228_POST_PLL_CTRL_MANUAL BIT(0)
+/* REG: 0xe0 */
+#define RK3228_POST_PLL_POWER_DOWN BIT(5)
+#define RK3228_POST_PLL_POWER_UP 0
+#define RK3228_PRE_PLL_POWER_DOWN BIT(4)
+#define RK3228_RXSENSE_CLK_CH_MASK BIT(3)
+#define RK3228_RXSENSE_CLK_CH_ENABLE BIT(3)
+#define RK3228_RXSENSE_DATA_CH2_MASK BIT(2)
+#define RK3228_RXSENSE_DATA_CH2_ENABLE BIT(2)
+#define RK3228_RXSENSE_DATA_CH1_MASK BIT(1)
+#define RK3228_RXSENSE_DATA_CH1_ENABLE BIT(1)
+#define RK3228_RXSENSE_DATA_CH0_MASK BIT(0)
+#define RK3228_RXSENSE_DATA_CH0_ENABLE BIT(0)
+/* REG: 0xe1 */
+#define RK3228_BANDGAP_ENABLE BIT(4)
+#define RK3228_TMDS_DRIVER_ENABLE GENMASK(3, 0)
+/* REG: 0xe2 */
+#define RK3228_PRE_PLL_FB_DIV_8_MASK BIT(7)
+#define RK3228_PRE_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7)
+#define RK3228_PCLK_VCO_DIV_5_MASK BIT(5)
+#define RK3228_PCLK_VCO_DIV_5(x) UPDATE(x, 5, 5)
+#define RK3228_PRE_PLL_PRE_DIV_MASK GENMASK(4, 0)
+#define RK3228_PRE_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
+/* REG: 0xe3 */
+#define RK3228_PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
+/* REG: 0xe4 */
+#define RK3228_PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5)
+#define RK3228_PRE_PLL_PCLK_DIV_B_SHIFT 5
+#define RK3228_PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5)
+#define RK3228_PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0)
+#define RK3228_PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0)
+/* REG: 0xe5 */
+#define RK3228_PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5)
+#define RK3228_PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5)
+#define RK3228_PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0)
+#define RK3228_PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0)
+/* REG: 0xe6 */
+#define RK3228_PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(5, 4)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 5, 4)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(3, 2)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 3, 2)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(1, 0)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 1, 0)
+/* REG: 0xe8 */
+#define RK3228_PRE_PLL_LOCK_STATUS BIT(0)
+/* REG: 0xe9 */
+#define RK3228_POST_PLL_POST_DIV_ENABLE UPDATE(3, 7, 6)
+#define RK3228_POST_PLL_PRE_DIV_MASK GENMASK(4, 0)
+#define RK3228_POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
+/* REG: 0xea */
+#define RK3228_POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
+/* REG: 0xeb */
+#define RK3228_POST_PLL_FB_DIV_8_MASK BIT(7)
+#define RK3228_POST_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7)
+#define RK3228_POST_PLL_POST_DIV_MASK GENMASK(5, 4)
+#define RK3228_POST_PLL_POST_DIV(x) UPDATE(x, 5, 4)
+#define RK3228_POST_PLL_LOCK_STATUS BIT(0)
+/* REG: 0xee */
+#define RK3228_TMDS_CH_TA_ENABLE GENMASK(7, 4)
+/* REG: 0xef */
+#define RK3228_TMDS_CLK_CH_TA(x) UPDATE(x, 7, 6)
+#define RK3228_TMDS_DATA_CH2_TA(x) UPDATE(x, 5, 4)
+#define RK3228_TMDS_DATA_CH1_TA(x) UPDATE(x, 3, 2)
+#define RK3228_TMDS_DATA_CH0_TA(x) UPDATE(x, 1, 0)
+/* REG: 0xf0 */
+#define RK3228_TMDS_DATA_CH2_PRE_EMPHASIS_MASK GENMASK(5, 4)
+#define RK3228_TMDS_DATA_CH2_PRE_EMPHASIS(x) UPDATE(x, 5, 4)
+#define RK3228_TMDS_DATA_CH1_PRE_EMPHASIS_MASK GENMASK(3, 2)
+#define RK3228_TMDS_DATA_CH1_PRE_EMPHASIS(x) UPDATE(x, 3, 2)
+#define RK3228_TMDS_DATA_CH0_PRE_EMPHASIS_MASK GENMASK(1, 0)
+#define RK3228_TMDS_DATA_CH0_PRE_EMPHASIS(x) UPDATE(x, 1, 0)
+/* REG: 0xf1 */
+#define RK3228_TMDS_CLK_CH_OUTPUT_SWING(x) UPDATE(x, 7, 4)
+#define RK3228_TMDS_DATA_CH2_OUTPUT_SWING(x) UPDATE(x, 3, 0)
+/* REG: 0xf2 */
+#define RK3228_TMDS_DATA_CH1_OUTPUT_SWING(x) UPDATE(x, 7, 4)
+#define RK3228_TMDS_DATA_CH0_OUTPUT_SWING(x) UPDATE(x, 3, 0)
+
+
+/*
+ * ---- Registers for RK3328
+ */
/* REG: 0x01 */
#define RK3328_BYPASS_RXSENSE_EN BIT(2)
#define RK3328_BYPASS_POWERON_EN BIT(1)
@@ -177,6 +281,7 @@ struct inno_hdmi_phy_plat_ops {
};
enum inno_hdmi_phy_type {
+ INNO_HDMI_PHY_RK3228,
INNO_HDMI_PHY_RK3328,
};
@@ -388,6 +493,25 @@ static const struct post_pll_config post_pll_cfg_table[] = {
{ /* sentinel */ }
};
+/* phy tuning values for an undocumented set of registers */
+static const struct phy_config rk3228_phy_cfg[] = {
+ { 165000000, {
+ 0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }, {
+ 340000000, {
+ 0xaa, 0x15, 0x6a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }, {
+ 594000000, {
+ 0xaa, 0x15, 0x7a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }, { /* sentinel */ },
+};
+
/* phy tuning values for an undocumented set of registers */
static const struct phy_config rk3328_phy_cfg[] = {
{ 165000000, {
@@ -453,6 +577,46 @@ static unsigned long inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno,
}
}
+static
+unsigned long inno_hdmi_phy_rk3228_clk_recalc_rate(struct phy *phy,
+ unsigned long parent_rate)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+ u64 rate, vco;
+ u8 nd, no_a, no_b, no_d;
+ __maybe_unused u8 no_c;
+ u16 nf;
+
+ nd = inno_read(inno, 0xe2) & RK3228_PRE_PLL_PRE_DIV_MASK;
+ nf = (inno_read(inno, 0xe2) & RK3228_PRE_PLL_FB_DIV_8_MASK) << 1;
+ nf |= inno_read(inno, 0xe3);
+ vco = parent_rate * nf;
+
+ if (inno_read(inno, 0xe2) & RK3228_PCLK_VCO_DIV_5_MASK) {
+ rate = vco / (nd * 5);
+ } else {
+ no_a = inno_read(inno, 0xe4) & RK3228_PRE_PLL_PCLK_DIV_A_MASK;
+ if (!no_a)
+ no_a = 1;
+ no_b = inno_read(inno, 0xe4) & RK3228_PRE_PLL_PCLK_DIV_B_MASK;
+ no_b >>= RK3228_PRE_PLL_PCLK_DIV_B_SHIFT;
+ no_b += 2;
+ no_d = inno_read(inno, 0xe5) & RK3228_PRE_PLL_PCLK_DIV_D_MASK;
+
+ if (no_a == 1)
+ rate = vco / (nd * no_b * no_d * 2);
+ else
+ rate = vco / (nd * no_a * no_d * 2);
+
+ }
+
+ inno->pixclock = rate;
+
+ dev_info(phy->dev, "rate %lu vco %llu\n", inno->pixclock, vco);
+
+ return inno->pixclock;
+}
+
static
unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct phy *phy,
unsigned long parent_rate)
@@ -494,6 +658,23 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct phy *phy,
return inno->pixclock;
}
+static long inno_hdmi_phy_rk3228_clk_round_rate(struct phy *phy,
+ unsigned long rate)
+{
+ const struct pre_pll_config *cfg = pre_pll_cfg_table;
+
+ rate = (rate / 1000) * 1000;
+
+ for (; cfg->pixclock != 0; cfg++)
+ if (cfg->pixclock == rate)
+ break;
+
+ if (cfg->pixclock == 0)
+ return -EINVAL;
+
+ return cfg->pixclock;
+}
+
static long inno_hdmi_phy_rk3328_clk_round_rate(struct phy *phy,
unsigned long rate)
{
@@ -528,6 +709,71 @@ struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
return cfg;
}
+static int
+inno_hdmi_phy_rk3228_clk_set_rate(struct phy *phy,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+ unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
+ const struct pre_pll_config *cfg;
+
+ int ret;
+ u32 val;
+
+ dev_info(phy->dev, "rate %lu tmdsclk %lu\n", rate, tmdsclock);
+
+ if (inno->pixclock == rate && inno->tmdsclock == tmdsclock)
+ return 0;
+
+ cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate);
+ if (IS_ERR(cfg))
+ return PTR_ERR(cfg);
+
+ /* Power down PRE-PLL */
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN,
+ RK3228_PRE_PLL_POWER_DOWN);
+
+ inno_update_bits(inno, 0xe2, RK3228_PRE_PLL_FB_DIV_8_MASK |
+ RK3228_PCLK_VCO_DIV_5_MASK |
+ RK3228_PRE_PLL_PRE_DIV_MASK,
+ RK3228_PRE_PLL_FB_DIV_8(cfg->fbdiv) |
+ RK3228_PCLK_VCO_DIV_5(cfg->vco_div_5_en) |
+ RK3228_PRE_PLL_PRE_DIV(cfg->prediv));
+ inno_write(inno, 0xe3, RK3228_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
+ inno_update_bits(inno, 0xe4, RK3228_PRE_PLL_PCLK_DIV_B_MASK |
+ RK3228_PRE_PLL_PCLK_DIV_A_MASK,
+ RK3228_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b) |
+ RK3228_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a));
+ inno_update_bits(inno, 0xe5, RK3228_PRE_PLL_PCLK_DIV_C_MASK |
+ RK3228_PRE_PLL_PCLK_DIV_D_MASK,
+ RK3228_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
+ RK3228_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d));
+ inno_update_bits(inno, 0xe6, RK3228_PRE_PLL_TMDSCLK_DIV_C_MASK |
+ RK3228_PRE_PLL_TMDSCLK_DIV_A_MASK |
+ RK3228_PRE_PLL_TMDSCLK_DIV_B_MASK,
+ RK3228_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
+ RK3228_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
+ RK3228_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b));
+
+ /* Power up PRE-PLL */
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN, 0);
+
+ /* Wait for Pre-PLL lock */
+ ret = inno_poll(inno, 0xe8, val, val & RK3228_PRE_PLL_LOCK_STATUS,
+ 1000, 10000);
+ if (ret) {
+ dev_err(phy->dev, "Pre-PLL locking failed\n");
+ return ret;
+ }
+
+ inno->pixclock = rate;
+ inno->tmdsclock = tmdsclock;
+
+ return 0;
+}
+
static int
inno_hdmi_phy_rk3328_clk_set_rate(struct phy *phy,
unsigned long rate,
@@ -588,6 +834,13 @@ inno_hdmi_phy_rk3328_clk_set_rate(struct phy *phy,
return 0;
}
+static void inno_hdmi_phy_rk3228_clk_enable(struct phy *phy)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN, 0);
+}
+
static void inno_hdmi_phy_rk3328_clk_enable(struct phy *phy)
{
struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
@@ -595,6 +848,14 @@ static void inno_hdmi_phy_rk3328_clk_enable(struct phy *phy)
inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
}
+static void inno_hdmi_phy_rk3228_clk_disable(struct phy *phy)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN,
+ RK3228_PRE_PLL_POWER_DOWN);
+}
+
static void inno_hdmi_phy_rk3328_clk_disable(struct phy *phy)
{
struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
@@ -603,6 +864,65 @@ static void inno_hdmi_phy_rk3328_clk_disable(struct phy *phy)
RK3328_PRE_PLL_POWER_DOWN);
}
+static int
+inno_hdmi_phy_rk3228_power_on(struct phy *phy,
+ const struct post_pll_config *cfg,
+ const struct phy_config *phy_cfg)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+ u32 val;
+ int ret;
+
+ /* set pdata_en to 0 */
+ inno_update_bits(inno, 0x02, RK3228_PDATA_EN_DISABLE, RK3228_PDATA_EN_DISABLE);
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN | RK3228_POST_PLL_POWER_DOWN,
+ RK3228_PRE_PLL_POWER_DOWN | RK3228_POST_PLL_POWER_DOWN);
+
+ /* Post-PLL update */
+ inno_update_bits(inno, 0xe9, RK3228_POST_PLL_PRE_DIV_MASK,
+ RK3228_POST_PLL_PRE_DIV(cfg->prediv));
+ inno_update_bits(inno, 0xeb, RK3228_POST_PLL_FB_DIV_8_MASK,
+ RK3228_POST_PLL_FB_DIV_8(cfg->fbdiv));
+ inno_write(inno, 0xea, RK3228_POST_PLL_FB_DIV_7_0(cfg->fbdiv));
+
+ if (cfg->postdiv == 1) {
+ inno_update_bits(inno, 0xe9, RK3228_POST_PLL_POST_DIV_ENABLE, 0);
+ } else {
+ int div = cfg->postdiv / 2 - 1;
+
+ inno_update_bits(inno, 0xe9, RK3228_POST_PLL_POST_DIV_ENABLE,
+ RK3228_POST_PLL_POST_DIV_ENABLE);
+ inno_update_bits(inno, 0xeb, RK3228_POST_PLL_POST_DIV_MASK,
+ RK3228_POST_PLL_POST_DIV(div));
+ }
+
+ for (val = 0; val < 4; val++)
+ inno_write(inno, 0xef + val, phy_cfg->regs[val]);
+
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN |
+ RK3228_POST_PLL_POWER_DOWN, 0);
+ inno_update_bits(inno, 0xe1, RK3228_BANDGAP_ENABLE,
+ RK3228_BANDGAP_ENABLE);
+ inno_update_bits(inno, 0xe1, RK3228_TMDS_DRIVER_ENABLE,
+ RK3228_TMDS_DRIVER_ENABLE);
+
+ /* Wait for post PLL lock */
+ ret = inno_poll(inno, 0xeb, val, val & RK3228_POST_PLL_LOCK_STATUS,
+ 1000, 10000);
+ if (ret) {
+ dev_err(phy->dev, "Post-PLL locking failed\n");
+ return ret;
+ }
+
+ if (phy_cfg->tmdsclock > 340000000)
+ mdelay(100);
+
+ /* set pdata_en_disable to 0 */
+ inno_update_bits(inno, 0x02, RK3228_PDATA_EN_DISABLE, 0);
+
+ return 0;
+}
+
static int
inno_hdmi_phy_rk3328_power_on(struct phy *phy,
const struct post_pll_config *cfg,
@@ -695,6 +1015,18 @@ inno_hdmi_phy_rk3328_power_on(struct phy *phy,
return 0;
}
+static void inno_hdmi_phy_rk3228_power_off(struct phy *phy)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+ debug("%s\n", __func__);
+
+ inno_update_bits(inno, 0xe1, RK3228_TMDS_DRIVER_ENABLE, 0);
+ inno_update_bits(inno, 0xe1, RK3228_BANDGAP_ENABLE, 0);
+ inno_update_bits(inno, 0xe0, RK3228_POST_PLL_POWER_DOWN,
+ RK3228_POST_PLL_POWER_DOWN);
+}
+
static void inno_hdmi_phy_rk3328_power_off(struct phy *phy)
{
struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
@@ -709,6 +1041,32 @@ static void inno_hdmi_phy_rk3328_power_off(struct phy *phy)
inno_write(inno, 0x07, 0);
}
+static void inno_hdmi_phy_rk3228_init(struct phy *phy)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+ const struct inno_hdmi_phy_plat_ops *plat_ops = inno->data->plat_ops;
+
+ debug("[PHY] %s: begin!\n", __func__);
+
+ /*
+ * Use phy internal register control
+ * rxsense/poweron/pllpd/pdataen signal.
+ */
+ inno_write(inno, 0x01, RK3228_BYPASS_RXSENSE_EN | RK3228_BYPASS_PWRON_EN | RK3228_BYPASS_PLLPD_EN);
+ inno_update_bits(inno, 0x02, RK3228_BYPASS_PDATA_EN, RK3228_BYPASS_PDATA_EN);
+
+ /* manual power down post-PLL */
+ inno_update_bits(inno, 0xaa, RK3228_POST_PLL_CTRL_MANUAL, RK3228_POST_PLL_CTRL_MANUAL);
+
+ if (plat_ops->clk_recalc_rate)
+ plat_ops->clk_recalc_rate(phy, clk_get_rate(&inno->refoclk));
+
+ if (plat_ops->clk_round_rate)
+ plat_ops->clk_round_rate(phy, inno->pixclock);
+
+ debug("[PHY] %s: done!\n", __func__);
+}
+
static void inno_hdmi_phy_rk3328_init(struct phy *phy)
{
struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
@@ -735,6 +1093,17 @@ static void inno_hdmi_phy_rk3328_init(struct phy *phy)
plat_ops->clk_round_rate(phy, inno->pixclock);
}
+static const struct inno_hdmi_phy_plat_ops rk3228_hdmi_phy_plat_ops = {
+ .init = inno_hdmi_phy_rk3228_init,
+ .power_on = inno_hdmi_phy_rk3228_power_on,
+ .power_off = inno_hdmi_phy_rk3228_power_off,
+ .clk_enable = inno_hdmi_phy_rk3228_clk_enable,
+ .clk_disable = inno_hdmi_phy_rk3228_clk_disable,
+ .clk_recalc_rate = inno_hdmi_phy_rk3228_clk_recalc_rate,
+ .clk_round_rate = inno_hdmi_phy_rk3228_clk_round_rate,
+ .clk_set_rate = inno_hdmi_phy_rk3228_clk_set_rate,
+};
+
static const struct inno_hdmi_phy_plat_ops rk3328_hdmi_phy_plat_ops = {
.init = inno_hdmi_phy_rk3328_init,
.power_on = inno_hdmi_phy_rk3328_power_on,
@@ -861,6 +1230,12 @@ static int inno_hdmi_phy_probe(struct udevice *dev)
return 0;
}
+static const struct inno_hdmi_phy_data rk3228_inno_hdmi_phy_drv_data = {
+ .phy_type = INNO_HDMI_PHY_RK3228,
+ .plat_ops = &rk3228_hdmi_phy_plat_ops,
+ .phy_cfg_table = rk3228_phy_cfg,
+};
+
static const struct inno_hdmi_phy_data rk3328_inno_hdmi_phy_drv_data = {
.phy_type = INNO_HDMI_PHY_RK3328,
.plat_ops = &rk3328_hdmi_phy_plat_ops,
@@ -868,6 +1243,10 @@ static const struct inno_hdmi_phy_data rk3328_inno_hdmi_phy_drv_data = {
};
static const struct udevice_id inno_hdmi_phy_ids[] = {
+ {
+ .compatible = "rockchip,rk3228-hdmi-phy",
+ .data = (ulong)&rk3228_inno_hdmi_phy_drv_data,
+ },
{
.compatible = "rockchip,rk3328-hdmi-phy",
.data = (ulong)&rk3328_inno_hdmi_phy_drv_data,
--
Armbian