Commit 880cee0b authored by Thierry Reding's avatar Thierry Reding

drm/tegra: sor: Parameterize register offsets

Future Tegra generations have an increased number of display controllers
that can drive individual SORs. In order to support that, the offset and
layout of some registers has changed in backwards-incompatible ways. Use
parameterized register offsets to support this.
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 7772fdae
...@@ -144,12 +144,29 @@ static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = { ...@@ -144,12 +144,29 @@ static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
}; };
#endif #endif
struct tegra_sor_regs {
unsigned int head_state0;
unsigned int head_state1;
unsigned int head_state2;
unsigned int head_state3;
unsigned int head_state4;
unsigned int head_state5;
unsigned int pll0;
unsigned int pll1;
unsigned int pll2;
unsigned int pll3;
unsigned int dp_padctl0;
unsigned int dp_padctl2;
};
struct tegra_sor_soc { struct tegra_sor_soc {
bool supports_edp; bool supports_edp;
bool supports_lvds; bool supports_lvds;
bool supports_hdmi; bool supports_hdmi;
bool supports_dp; bool supports_dp;
const struct tegra_sor_regs *regs;
const struct tegra_sor_hdmi_settings *settings; const struct tegra_sor_hdmi_settings *settings;
unsigned int num_settings; unsigned int num_settings;
...@@ -387,23 +404,23 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor, ...@@ -387,23 +404,23 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
/* disable LVDS mode */ /* disable LVDS mode */
tegra_sor_writel(sor, 0, SOR_LVDS); tegra_sor_writel(sor, 0, SOR_LVDS);
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value |= SOR_DP_PADCTL_TX_PU_ENABLE; value |= SOR_DP_PADCTL_TX_PU_ENABLE;
value &= ~SOR_DP_PADCTL_TX_PU_MASK; value &= ~SOR_DP_PADCTL_TX_PU_MASK;
value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */ value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0; SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0;
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
usleep_range(10, 100); usleep_range(10, 100);
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0); SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
err = drm_dp_aux_prepare(sor->aux, DP_SET_ANSI_8B10B); err = drm_dp_aux_prepare(sor->aux, DP_SET_ANSI_8B10B);
if (err < 0) if (err < 0)
...@@ -895,31 +912,31 @@ static void tegra_sor_mode_set(struct tegra_sor *sor, ...@@ -895,31 +912,31 @@ static void tegra_sor_mode_set(struct tegra_sor *sor,
*/ */
value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff); value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe)); tegra_sor_writel(sor, value, sor->soc->regs->head_state1 + dc->pipe);
/* sync end = sync width - 1 */ /* sync end = sync width - 1 */
vse = mode->vsync_end - mode->vsync_start - 1; vse = mode->vsync_end - mode->vsync_start - 1;
hse = mode->hsync_end - mode->hsync_start - 1; hse = mode->hsync_end - mode->hsync_start - 1;
value = ((vse & 0x7fff) << 16) | (hse & 0x7fff); value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe)); tegra_sor_writel(sor, value, sor->soc->regs->head_state2 + dc->pipe);
/* blank end = sync end + back porch */ /* blank end = sync end + back porch */
vbe = vse + (mode->vtotal - mode->vsync_end); vbe = vse + (mode->vtotal - mode->vsync_end);
hbe = hse + (mode->htotal - mode->hsync_end); hbe = hse + (mode->htotal - mode->hsync_end);
value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff); value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe)); tegra_sor_writel(sor, value, sor->soc->regs->head_state3 + dc->pipe);
/* blank start = blank end + active */ /* blank start = blank end + active */
vbs = vbe + mode->vdisplay; vbs = vbe + mode->vdisplay;
hbs = hbe + mode->hdisplay; hbs = hbe + mode->hdisplay;
value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff); value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe)); tegra_sor_writel(sor, value, sor->soc->regs->head_state4 + dc->pipe);
/* XXX interlacing support */ /* XXX interlacing support */
tegra_sor_writel(sor, 0x001, SOR_HEAD_STATE5(dc->pipe)); tegra_sor_writel(sor, 0x001, sor->soc->regs->head_state5 + dc->pipe);
} }
static int tegra_sor_detach(struct tegra_sor *sor) static int tegra_sor_detach(struct tegra_sor *sor)
...@@ -1001,10 +1018,10 @@ static int tegra_sor_power_down(struct tegra_sor *sor) ...@@ -1001,10 +1018,10 @@ static int tegra_sor_power_down(struct tegra_sor *sor)
return err; return err;
} }
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2); SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2);
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
/* stop lane sequencer */ /* stop lane sequencer */
value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP | value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP |
...@@ -1024,20 +1041,20 @@ static int tegra_sor_power_down(struct tegra_sor *sor) ...@@ -1024,20 +1041,20 @@ static int tegra_sor_power_down(struct tegra_sor *sor)
if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0) if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0)
return -ETIMEDOUT; return -ETIMEDOUT;
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value |= SOR_PLL2_PORT_POWERDOWN; value |= SOR_PLL2_PORT_POWERDOWN;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
usleep_range(20, 100); usleep_range(20, 100);
value = tegra_sor_readl(sor, SOR_PLL0); value = tegra_sor_readl(sor, sor->soc->regs->pll0);
value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR; value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
tegra_sor_writel(sor, value, SOR_PLL0); tegra_sor_writel(sor, value, sor->soc->regs->pll0);
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value |= SOR_PLL2_SEQ_PLLCAPPD; value |= SOR_PLL2_SEQ_PLLCAPPD;
value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE; value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
usleep_range(20, 100); usleep_range(20, 100);
...@@ -1528,40 +1545,40 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1528,40 +1545,40 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK; value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
tegra_sor_writel(sor, value, SOR_CLK_CNTRL); tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value &= ~SOR_PLL2_BANDGAP_POWERDOWN; value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
usleep_range(20, 100); usleep_range(20, 100);
value = tegra_sor_readl(sor, SOR_PLL3); value = tegra_sor_readl(sor, sor->soc->regs->pll3);
value |= SOR_PLL3_PLL_VDD_MODE_3V3; value |= SOR_PLL3_PLL_VDD_MODE_3V3;
tegra_sor_writel(sor, value, SOR_PLL3); tegra_sor_writel(sor, value, sor->soc->regs->pll3);
value = SOR_PLL0_ICHPMP(0xf) | SOR_PLL0_VCOCAP_RST | value = SOR_PLL0_ICHPMP(0xf) | SOR_PLL0_VCOCAP_RST |
SOR_PLL0_PLLREG_LEVEL_V45 | SOR_PLL0_RESISTOR_EXT; SOR_PLL0_PLLREG_LEVEL_V45 | SOR_PLL0_RESISTOR_EXT;
tegra_sor_writel(sor, value, SOR_PLL0); tegra_sor_writel(sor, value, sor->soc->regs->pll0);
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value |= SOR_PLL2_SEQ_PLLCAPPD; value |= SOR_PLL2_SEQ_PLLCAPPD;
value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE; value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
value |= SOR_PLL2_LVDS_ENABLE; value |= SOR_PLL2_LVDS_ENABLE;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
value = SOR_PLL1_TERM_COMPOUT | SOR_PLL1_TMDS_TERM; value = SOR_PLL1_TERM_COMPOUT | SOR_PLL1_TMDS_TERM;
tegra_sor_writel(sor, value, SOR_PLL1); tegra_sor_writel(sor, value, sor->soc->regs->pll1);
while (true) { while (true) {
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
if ((value & SOR_PLL2_SEQ_PLLCAPPD_ENFORCE) == 0) if ((value & SOR_PLL2_SEQ_PLLCAPPD_ENFORCE) == 0)
break; break;
usleep_range(250, 1000); usleep_range(250, 1000);
} }
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value &= ~SOR_PLL2_POWERDOWN_OVERRIDE; value &= ~SOR_PLL2_POWERDOWN_OVERRIDE;
value &= ~SOR_PLL2_PORT_POWERDOWN; value &= ~SOR_PLL2_PORT_POWERDOWN;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
/* /*
* power up * power up
...@@ -1574,18 +1591,18 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1574,18 +1591,18 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
tegra_sor_writel(sor, value, SOR_CLK_CNTRL); tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
/* step 1 */ /* step 1 */
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL2_PORT_POWERDOWN | value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL2_PORT_POWERDOWN |
SOR_PLL2_BANDGAP_POWERDOWN; SOR_PLL2_BANDGAP_POWERDOWN;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
value = tegra_sor_readl(sor, SOR_PLL0); value = tegra_sor_readl(sor, sor->soc->regs->pll0);
value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR; value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
tegra_sor_writel(sor, value, SOR_PLL0); tegra_sor_writel(sor, value, sor->soc->regs->pll0);
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value &= ~SOR_DP_PADCTL_PAD_CAL_PD; value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
/* step 2 */ /* step 2 */
err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS); err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS);
...@@ -1595,28 +1612,28 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1595,28 +1612,28 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
usleep_range(5, 100); usleep_range(5, 100);
/* step 3 */ /* step 3 */
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value &= ~SOR_PLL2_BANDGAP_POWERDOWN; value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
usleep_range(20, 100); usleep_range(20, 100);
/* step 4 */ /* step 4 */
value = tegra_sor_readl(sor, SOR_PLL0); value = tegra_sor_readl(sor, sor->soc->regs->pll0);
value &= ~SOR_PLL0_VCOPD; value &= ~SOR_PLL0_VCOPD;
value &= ~SOR_PLL0_PWR; value &= ~SOR_PLL0_PWR;
tegra_sor_writel(sor, value, SOR_PLL0); tegra_sor_writel(sor, value, sor->soc->regs->pll0);
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE; value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
usleep_range(200, 1000); usleep_range(200, 1000);
/* step 5 */ /* step 5 */
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value &= ~SOR_PLL2_PORT_POWERDOWN; value &= ~SOR_PLL2_PORT_POWERDOWN;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
/* XXX not in TRM */ /* XXX not in TRM */
for (value = 0, i = 0; i < 5; i++) for (value = 0, i = 0; i < 5; i++)
...@@ -1632,7 +1649,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1632,7 +1649,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
dev_err(sor->dev, "failed to set parent clock: %d\n", err); dev_err(sor->dev, "failed to set parent clock: %d\n", err);
/* power DP lanes */ /* power DP lanes */
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
if (link.num_lanes <= 2) if (link.num_lanes <= 2)
value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2); value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2);
...@@ -1649,7 +1666,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1649,7 +1666,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
else else
value |= SOR_DP_PADCTL_PD_TXD_0; value |= SOR_DP_PADCTL_PD_TXD_0;
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
value = tegra_sor_readl(sor, SOR_DP_LINKCTL0); value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
...@@ -1693,9 +1710,9 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1693,9 +1710,9 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
tegra_sor_writel(sor, value, SOR_DP_TPG); tegra_sor_writel(sor, value, SOR_DP_TPG);
/* enable pad calibration logic */ /* enable pad calibration logic */
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value |= SOR_DP_PADCTL_PAD_CAL_PD; value |= SOR_DP_PADCTL_PAD_CAL_PD;
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
err = drm_dp_link_probe(sor->aux, &link); err = drm_dp_link_probe(sor->aux, &link);
if (err < 0) if (err < 0)
...@@ -2017,38 +2034,38 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -2017,38 +2034,38 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
usleep_range(20, 100); usleep_range(20, 100);
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value &= ~SOR_PLL2_BANDGAP_POWERDOWN; value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
usleep_range(20, 100); usleep_range(20, 100);
value = tegra_sor_readl(sor, SOR_PLL3); value = tegra_sor_readl(sor, sor->soc->regs->pll3);
value &= ~SOR_PLL3_PLL_VDD_MODE_3V3; value &= ~SOR_PLL3_PLL_VDD_MODE_3V3;
tegra_sor_writel(sor, value, SOR_PLL3); tegra_sor_writel(sor, value, sor->soc->regs->pll3);
value = tegra_sor_readl(sor, SOR_PLL0); value = tegra_sor_readl(sor, sor->soc->regs->pll0);
value &= ~SOR_PLL0_VCOPD; value &= ~SOR_PLL0_VCOPD;
value &= ~SOR_PLL0_PWR; value &= ~SOR_PLL0_PWR;
tegra_sor_writel(sor, value, SOR_PLL0); tegra_sor_writel(sor, value, sor->soc->regs->pll0);
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE; value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
usleep_range(200, 400); usleep_range(200, 400);
value = tegra_sor_readl(sor, SOR_PLL2); value = tegra_sor_readl(sor, sor->soc->regs->pll2);
value &= ~SOR_PLL2_POWERDOWN_OVERRIDE; value &= ~SOR_PLL2_POWERDOWN_OVERRIDE;
value &= ~SOR_PLL2_PORT_POWERDOWN; value &= ~SOR_PLL2_PORT_POWERDOWN;
tegra_sor_writel(sor, value, SOR_PLL2); tegra_sor_writel(sor, value, sor->soc->regs->pll2);
usleep_range(20, 100); usleep_range(20, 100);
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2; SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2;
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
while (true) { while (true) {
value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
...@@ -2166,9 +2183,9 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -2166,9 +2183,9 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
tegra_sor_writel(sor, value, SOR_STATE1); tegra_sor_writel(sor, value, SOR_STATE1);
/* power up pad calibration */ /* power up pad calibration */
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value &= ~SOR_DP_PADCTL_PAD_CAL_PD; value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
/* production settings */ /* production settings */
settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000); settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000);
...@@ -2178,24 +2195,24 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -2178,24 +2195,24 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
return; return;
} }
value = tegra_sor_readl(sor, SOR_PLL0); value = tegra_sor_readl(sor, sor->soc->regs->pll0);
value &= ~SOR_PLL0_ICHPMP_MASK; value &= ~SOR_PLL0_ICHPMP_MASK;
value &= ~SOR_PLL0_VCOCAP_MASK; value &= ~SOR_PLL0_VCOCAP_MASK;
value |= SOR_PLL0_ICHPMP(settings->ichpmp); value |= SOR_PLL0_ICHPMP(settings->ichpmp);
value |= SOR_PLL0_VCOCAP(settings->vcocap); value |= SOR_PLL0_VCOCAP(settings->vcocap);
tegra_sor_writel(sor, value, SOR_PLL0); tegra_sor_writel(sor, value, sor->soc->regs->pll0);
tegra_sor_dp_term_calibrate(sor); tegra_sor_dp_term_calibrate(sor);
value = tegra_sor_readl(sor, SOR_PLL1); value = tegra_sor_readl(sor, sor->soc->regs->pll1);
value &= ~SOR_PLL1_LOADADJ_MASK; value &= ~SOR_PLL1_LOADADJ_MASK;
value |= SOR_PLL1_LOADADJ(settings->loadadj); value |= SOR_PLL1_LOADADJ(settings->loadadj);
tegra_sor_writel(sor, value, SOR_PLL1); tegra_sor_writel(sor, value, sor->soc->regs->pll1);
value = tegra_sor_readl(sor, SOR_PLL3); value = tegra_sor_readl(sor, sor->soc->regs->pll3);
value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK; value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK;
value |= SOR_PLL3_BG_VREF_LEVEL(settings->bg_vref); value |= SOR_PLL3_BG_VREF_LEVEL(settings->bg_vref);
tegra_sor_writel(sor, value, SOR_PLL3); tegra_sor_writel(sor, value, sor->soc->regs->pll3);
value = settings->drive_current[0] << 24 | value = settings->drive_current[0] << 24 |
settings->drive_current[1] << 16 | settings->drive_current[1] << 16 |
...@@ -2209,16 +2226,16 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -2209,16 +2226,16 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
settings->preemphasis[3] << 0; settings->preemphasis[3] << 0;
tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0); tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value &= ~SOR_DP_PADCTL_TX_PU_MASK; value &= ~SOR_DP_PADCTL_TX_PU_MASK;
value |= SOR_DP_PADCTL_TX_PU_ENABLE; value |= SOR_DP_PADCTL_TX_PU_ENABLE;
value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu); value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu);
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
/* power down pad calibration */ /* power down pad calibration */
value = tegra_sor_readl(sor, SOR_DP_PADCTL0); value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
value |= SOR_DP_PADCTL_PAD_CAL_PD; value |= SOR_DP_PADCTL_PAD_CAL_PD;
tegra_sor_writel(sor, value, SOR_DP_PADCTL0); tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
/* miscellaneous display controller settings */ /* miscellaneous display controller settings */
value = VSYNC_H_POSITION(1); value = VSYNC_H_POSITION(1);
...@@ -2250,16 +2267,16 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -2250,16 +2267,16 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
dev_err(sor->dev, "failed to power up SOR: %d\n", err); dev_err(sor->dev, "failed to power up SOR: %d\n", err);
/* configure dynamic range of output */ /* configure dynamic range of output */
value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe)); value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK; value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK;
value &= ~SOR_HEAD_STATE_DYNRANGE_MASK; value &= ~SOR_HEAD_STATE_DYNRANGE_MASK;
tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
/* configure colorspace */ /* configure colorspace */
value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe)); value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
value &= ~SOR_HEAD_STATE_COLORSPACE_MASK; value &= ~SOR_HEAD_STATE_COLORSPACE_MASK;
value |= SOR_HEAD_STATE_COLORSPACE_RGB; value |= SOR_HEAD_STATE_COLORSPACE_RGB;
tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
tegra_sor_mode_set(sor, mode, state); tegra_sor_mode_set(sor, mode, state);
...@@ -2488,19 +2505,51 @@ static const u8 tegra124_sor_xbar_cfg[5] = { ...@@ -2488,19 +2505,51 @@ static const u8 tegra124_sor_xbar_cfg[5] = {
0, 1, 2, 3, 4 0, 1, 2, 3, 4
}; };
static const struct tegra_sor_regs tegra124_sor_regs = {
.head_state0 = 0x05,
.head_state1 = 0x07,
.head_state2 = 0x09,
.head_state3 = 0x0b,
.head_state4 = 0x0d,
.head_state5 = 0x0f,
.pll0 = 0x17,
.pll1 = 0x18,
.pll2 = 0x19,
.pll3 = 0x1a,
.dp_padctl0 = 0x5c,
.dp_padctl2 = 0x73,
};
static const struct tegra_sor_soc tegra124_sor = { static const struct tegra_sor_soc tegra124_sor = {
.supports_edp = true, .supports_edp = true,
.supports_lvds = true, .supports_lvds = true,
.supports_hdmi = false, .supports_hdmi = false,
.supports_dp = false, .supports_dp = false,
.regs = &tegra124_sor_regs,
.xbar_cfg = tegra124_sor_xbar_cfg, .xbar_cfg = tegra124_sor_xbar_cfg,
}; };
static const struct tegra_sor_regs tegra210_sor_regs = {
.head_state0 = 0x05,
.head_state1 = 0x07,
.head_state2 = 0x09,
.head_state3 = 0x0b,
.head_state4 = 0x0d,
.head_state5 = 0x0f,
.pll0 = 0x17,
.pll1 = 0x18,
.pll2 = 0x19,
.pll3 = 0x1a,
.dp_padctl0 = 0x5c,
.dp_padctl2 = 0x73,
};
static const struct tegra_sor_soc tegra210_sor = { static const struct tegra_sor_soc tegra210_sor = {
.supports_edp = true, .supports_edp = true,
.supports_lvds = false, .supports_lvds = false,
.supports_hdmi = false, .supports_hdmi = false,
.supports_dp = false, .supports_dp = false,
.regs = &tegra210_sor_regs,
.xbar_cfg = tegra124_sor_xbar_cfg, .xbar_cfg = tegra124_sor_xbar_cfg,
}; };
...@@ -2514,6 +2563,8 @@ static const struct tegra_sor_soc tegra210_sor1 = { ...@@ -2514,6 +2563,8 @@ static const struct tegra_sor_soc tegra210_sor1 = {
.supports_hdmi = true, .supports_hdmi = true,
.supports_dp = true, .supports_dp = true,
.regs = &tegra210_sor_regs,
.num_settings = ARRAY_SIZE(tegra210_sor_hdmi_defaults), .num_settings = ARRAY_SIZE(tegra210_sor_hdmi_defaults),
.settings = tegra210_sor_hdmi_defaults, .settings = tegra210_sor_hdmi_defaults,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment