diff options
author | Aaron Durbin <adurbin@chromium.org> | 2016-08-06 13:42:37 -0500 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2016-08-09 01:32:21 +0200 |
commit | 9ba069957b1591628ea4d5e2a9ff8553efa52c71 (patch) | |
tree | 0f370b43773242ce704158c676f964432230cb3b /src/soc/nvidia/tegra132/sor.c | |
parent | 0c634159a35ff567fc4897df25dddddd181a1a8c (diff) |
soc/nvidia/tegra132: remove tegra132 support
As no more mainboards are utilizing this SoC support code remove
it. It can be resurrected if ever needed.
BUG=chrome-os-partner:55932
Change-Id: Ic3caf6e6c9b62d012679b996abaa525c8bf679a9
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/16108
Tested-by: build bot (Jenkins)
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Diffstat (limited to 'src/soc/nvidia/tegra132/sor.c')
-rw-r--r-- | src/soc/nvidia/tegra132/sor.c | 1100 |
1 files changed, 0 insertions, 1100 deletions
diff --git a/src/soc/nvidia/tegra132/sor.c b/src/soc/nvidia/tegra132/sor.c deleted file mode 100644 index baa06853b8..0000000000 --- a/src/soc/nvidia/tegra132/sor.c +++ /dev/null @@ -1,1100 +0,0 @@ -/* - * drivers/video/tegra/dc/sor.c - * - * Copyright (c) 2011-2015, NVIDIA Corporation. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <console/console.h> -#include <arch/io.h> -#include <stdint.h> -#include <lib.h> -#include <stdlib.h> -#include <delay.h> -#include <soc/addressmap.h> -#include <device/device.h> -#include <stdlib.h> -#include <string.h> -#include <cpu/cpu.h> -#include <boot/tables.h> -#include <cbmem.h> -#include <soc/nvidia/tegra/dc.h> -#include <soc/nvidia/tegra/types.h> -#include <soc/sor.h> -#include <soc/nvidia/tegra/displayport.h> -#include <soc/clk_rst.h> -#include <soc/clock.h> -#include "chip.h" -#include <soc/display.h> - -#define DEBUG_SOR 0 - -#define APBDEV_PMC_DPD_SAMPLE (0x20) -#define APBDEV_PMC_DPD_SAMPLE_ON_DISABLE (0) -#define APBDEV_PMC_DPD_SAMPLE_ON_ENABLE (1) -#define APBDEV_PMC_SEL_DPD_TIM (0x1c8) -#define APBDEV_PMC_SEL_DPD_TIM_SEL_DPD_TIM_DEFAULT (0x7f) -#define APBDEV_PMC_IO_DPD2_REQ (0x1c0) -#define APBDEV_PMC_IO_DPD2_REQ_LVDS_SHIFT (25) -#define APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF (0 << 25) -#define APBDEV_PMC_IO_DPD2_REQ_LVDS_ON (1 << 25) -#define APBDEV_PMC_IO_DPD2_REQ_CODE_SHIFT (30) -#define APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK (0x3 << 30) -#define APBDEV_PMC_IO_DPD2_REQ_CODE_IDLE (0 << 30) -#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF (1 << 30) -#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON (2 << 30) -#define APBDEV_PMC_IO_DPD2_STATUS (0x1c4) -#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_SHIFT (25) -#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_OFF (0 << 25) -#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON (1 << 25) - -#define DC_N_WINDOWS 5 - -static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg) -{ - void *addr = sor->base + (u32) (reg << 2); - u32 reg_val = READL(addr); - return reg_val; -} - -static inline void tegra_sor_writel(struct tegra_dc_sor_data *sor, - u32 reg, u32 val) -{ - void *addr = sor->base + (u32) (reg << 2); - WRITEL(val, addr); -} - -static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor, - u32 reg, u32 mask, u32 val) -{ - u32 reg_val = tegra_sor_readl(sor, reg); - reg_val &= ~mask; - reg_val |= val; - tegra_sor_writel(sor, reg, reg_val); -} - -void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor) -{ - tegra_sor_write_field(sor, - NV_SOR_DP_PADCTL(sor->portnum), - NV_SOR_DP_PADCTL_TX_PU_MASK, - NV_SOR_DP_PADCTL_TX_PU_DISABLE); -} - -void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask, - u32 pe_reg, u32 vs_reg, u32 pc_reg, u8 pc_supported) -{ - tegra_sor_write_field(sor, NV_SOR_PR(sor->portnum), - mask, pe_reg); - tegra_sor_write_field(sor, NV_SOR_DC(sor->portnum), - mask, vs_reg); - if (pc_supported) { - tegra_sor_write_field( - sor, NV_SOR_POSTCURSOR(sor->portnum), - mask, pc_reg); - } -} - -static u32 tegra_dc_sor_poll_register(struct tegra_dc_sor_data *sor, - u32 reg, u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_us) -{ - u32 temp = timeout_us; - u32 reg_val = 0; - - do { - udelay(poll_interval_us); - reg_val = tegra_sor_readl(sor, reg); - if (timeout_us > poll_interval_us) - timeout_us -= poll_interval_us; - else - break; - } while ((reg_val & mask) != exp_val); - - if ((reg_val & mask) == exp_val) - return 0; /* success */ - printk(BIOS_ERR, - "sor_poll_register 0x%x: timeout, " - "(reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n", - reg, reg_val, mask, exp_val); - - return temp; -} - -int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd) -{ - u32 reg_val; - u32 orig_val; - - orig_val = tegra_sor_readl(sor, NV_SOR_PWR); - - reg_val = pu_pd ? NV_SOR_PWR_NORMAL_STATE_PU : - NV_SOR_PWR_NORMAL_STATE_PD; /* normal state only */ - - if (reg_val == orig_val) - return 0; /* No update needed */ - - reg_val |= NV_SOR_PWR_SETTING_NEW_TRIGGER; - tegra_sor_writel(sor, NV_SOR_PWR, reg_val); - - /* Poll to confirm it is done */ - if (tegra_dc_sor_poll_register(sor, NV_SOR_PWR, - NV_SOR_PWR_SETTING_NEW_DEFAULT_MASK, - NV_SOR_PWR_SETTING_NEW_DONE, - 100, TEGRA_SOR_TIMEOUT_MS * 1000)) { - printk(BIOS_ERR, - "dc timeout waiting for SOR_PWR = NEW_DONE\n"); - return -EFAULT; - } - return 0; -} - -void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena, - u8 training_pattern, const struct tegra_dc_dp_link_config *link_cfg) -{ - u32 reg_val; - - reg_val = tegra_sor_readl(sor, NV_SOR_DP_LINKCTL(sor->portnum)); - - if (ena) - reg_val |= NV_SOR_DP_LINKCTL_ENABLE_YES; - else - reg_val &= NV_SOR_DP_LINKCTL_ENABLE_NO; - - reg_val &= ~NV_SOR_DP_LINKCTL_TUSIZE_MASK; - reg_val |= (link_cfg->tu_size << NV_SOR_DP_LINKCTL_TUSIZE_SHIFT); - - if (link_cfg->enhanced_framing) - reg_val |= NV_SOR_DP_LINKCTL_ENHANCEDFRAME_ENABLE; - - tegra_sor_writel(sor, NV_SOR_DP_LINKCTL(sor->portnum), reg_val); - - switch (training_pattern) { - case training_pattern_1: - tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x41414141); - break; - case training_pattern_2: - case training_pattern_3: - reg_val = (link_cfg->link_bw == SOR_LINK_SPEED_G5_4) ? - 0x43434343 : 0x42424242; - tegra_sor_writel(sor, NV_SOR_DP_TPG, reg_val); - break; - default: - tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x50505050); - break; - } -} - -static int tegra_dc_sor_enable_lane_sequencer(struct tegra_dc_sor_data *sor, - int pu, int is_lvds) -{ - u32 reg_val; - - /* SOR lane sequencer */ - if (pu) - reg_val = NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER | - NV_SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | - NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PU; - else - reg_val = NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER | - NV_SOR_LANE_SEQ_CTL_SEQUENCE_UP | - NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PD; - - if (is_lvds) - reg_val |= 15 << NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT; - else - reg_val |= 1 << NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT; - - tegra_sor_writel(sor, NV_SOR_LANE_SEQ_CTL, reg_val); - - if (tegra_dc_sor_poll_register(sor, NV_SOR_LANE_SEQ_CTL, - NV_SOR_LANE_SEQ_CTL_SETTING_MASK, - NV_SOR_LANE_SEQ_CTL_SETTING_NEW_DONE, - 100, TEGRA_SOR_TIMEOUT_MS*1000)) { - printk(BIOS_ERR, - "dp: timeout while waiting for SOR lane sequencer " - "to power down langes\n"); - return -1; - } - return 0; -} - -static int tegra_dc_sor_power_dplanes(struct tegra_dc_sor_data *sor, - u32 lane_count, int pu) -{ - u32 reg_val; - - reg_val = tegra_sor_readl(sor, NV_SOR_DP_PADCTL(sor->portnum)); - - if (pu) { - switch (lane_count) { - case 4: - reg_val |= (NV_SOR_DP_PADCTL_PD_TXD_3_NO | - NV_SOR_DP_PADCTL_PD_TXD_2_NO); - /* fall through */ - case 2: - reg_val |= NV_SOR_DP_PADCTL_PD_TXD_1_NO; - case 1: - reg_val |= NV_SOR_DP_PADCTL_PD_TXD_0_NO; - break; - default: - printk(BIOS_ERR, - "dp: invalid lane number %d\n", lane_count); - return -1; - } - - tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), reg_val); - tegra_dc_sor_set_lane_count(sor, lane_count); - } - return tegra_dc_sor_enable_lane_sequencer(sor, pu, 0); -} - -void tegra_dc_sor_set_panel_power(struct tegra_dc_sor_data *sor, - int power_up) -{ - u32 reg_val; - - reg_val = tegra_sor_readl(sor, NV_SOR_DP_PADCTL(sor->portnum)); - - if (power_up) - reg_val &= ~NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN; - else - reg_val |= NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN; - - tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), reg_val); -} - -static void tegra_dc_sor_config_pwm(struct tegra_dc_sor_data *sor, u32 pwm_div, - u32 pwm_dutycycle) -{ - tegra_sor_writel(sor, NV_SOR_PWM_DIV, pwm_div); - tegra_sor_writel(sor, NV_SOR_PWM_CTL, - (pwm_dutycycle & NV_SOR_PWM_CTL_DUTY_CYCLE_MASK) | - NV_SOR_PWM_CTL_SETTING_NEW_TRIGGER); - - if (tegra_dc_sor_poll_register(sor, NV_SOR_PWM_CTL, - NV_SOR_PWM_CTL_SETTING_NEW_SHIFT, - NV_SOR_PWM_CTL_SETTING_NEW_DONE, - 100, TEGRA_SOR_TIMEOUT_MS * 1000)) { - printk(BIOS_ERR, - "dp: timeout while waiting for SOR PWM setting\n"); - } -} - -static void tegra_dc_sor_set_dp_mode(struct tegra_dc_sor_data *sor, - const struct tegra_dc_dp_link_config *link_cfg) -{ - u32 reg_val; - - tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw); - - tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_none, link_cfg); - reg_val = tegra_sor_readl(sor, NV_SOR_DP_CONFIG(sor->portnum)); - reg_val &= ~NV_SOR_DP_CONFIG_WATERMARK_MASK; - reg_val |= link_cfg->watermark; - reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_MASK; - reg_val |= (link_cfg->active_count << - NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_SHIFT); - reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_MASK; - reg_val |= (link_cfg->active_frac << - NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_SHIFT); - if (link_cfg->activepolarity) - reg_val |= NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE; - else - reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE; - reg_val |= (NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE | - NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE); - - tegra_sor_writel(sor, NV_SOR_DP_CONFIG(sor->portnum), reg_val); - - /* program h/vblank sym */ - tegra_sor_write_field(sor, NV_SOR_DP_AUDIO_HBLANK_SYMBOLS, - NV_SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK, link_cfg->hblank_sym); - - tegra_sor_write_field(sor, NV_SOR_DP_AUDIO_VBLANK_SYMBOLS, - NV_SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK, link_cfg->vblank_sym); -} - -static inline void tegra_dc_sor_super_update(struct tegra_dc_sor_data *sor) -{ - tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 0); - tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 1); - tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 0); -} - -static inline void tegra_dc_sor_update(struct tegra_dc_sor_data *sor) -{ - tegra_sor_writel(sor, NV_SOR_STATE0, 0); - tegra_sor_writel(sor, NV_SOR_STATE0, 1); - tegra_sor_writel(sor, NV_SOR_STATE0, 0); -} - -static void tegra_dc_sor_io_set_dpd(struct tegra_dc_sor_data *sor, int up) -{ - u32 reg_val; - void *pmc_base = sor->pmc_base; - - if (up) { - WRITEL(APBDEV_PMC_DPD_SAMPLE_ON_ENABLE, - pmc_base + APBDEV_PMC_DPD_SAMPLE); - WRITEL(10, pmc_base + APBDEV_PMC_SEL_DPD_TIM); - } - - reg_val = READL(pmc_base + APBDEV_PMC_IO_DPD2_REQ); - reg_val &= ~(APBDEV_PMC_IO_DPD2_REQ_LVDS_ON || - APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK); - - reg_val = up ? APBDEV_PMC_IO_DPD2_REQ_LVDS_ON | - APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF : - APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF | - APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON; - - WRITEL(reg_val, pmc_base + APBDEV_PMC_IO_DPD2_REQ); - - /* Polling */ - u32 temp = 10*1000; - do { - udelay(20); - reg_val = READL(pmc_base + APBDEV_PMC_IO_DPD2_STATUS); - if (temp > 20) - temp -= 20; - else - break; - } while ((reg_val & APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON) != 0); - - if ((reg_val & APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON) != 0) - printk(BIOS_ERR, - "PMC_IO_DPD2 polling failed (0x%x)\n", reg_val); - - if (up) - WRITEL(APBDEV_PMC_DPD_SAMPLE_ON_DISABLE, - pmc_base + APBDEV_PMC_DPD_SAMPLE); -} - -void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int) -{ - u32 reg_val; - - reg_val = tegra_sor_readl(sor, NV_SOR_DP_SPARE(sor->portnum)); - if (is_int) - reg_val |= NV_SOR_DP_SPARE_PANEL_INTERNAL; - else - reg_val &= ~NV_SOR_DP_SPARE_PANEL_INTERNAL; - - reg_val |= NV_SOR_DP_SPARE_SOR_CLK_SEL_MACRO_SORCLK | - NV_SOR_DP_SPARE_SEQ_ENABLE_YES; - tegra_sor_writel(sor, NV_SOR_DP_SPARE(sor->portnum), reg_val); -} - -void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw, - u8 *lane_count) -{ - u32 reg_val; - - reg_val = tegra_sor_readl(sor, NV_SOR_CLK_CNTRL); - *link_bw = (reg_val & NV_SOR_CLK_CNTRL_DP_LINK_SPEED_MASK) - >> NV_SOR_CLK_CNTRL_DP_LINK_SPEED_SHIFT; - reg_val = tegra_sor_readl(sor, - NV_SOR_DP_LINKCTL(sor->portnum)); - - switch (reg_val & NV_SOR_DP_LINKCTL_LANECOUNT_MASK) { - case NV_SOR_DP_LINKCTL_LANECOUNT_ZERO: - *lane_count = 0; - break; - case NV_SOR_DP_LINKCTL_LANECOUNT_ONE: - *lane_count = 1; - break; - case NV_SOR_DP_LINKCTL_LANECOUNT_TWO: - *lane_count = 2; - break; - case NV_SOR_DP_LINKCTL_LANECOUNT_FOUR: - *lane_count = 4; - break; - default: - printk(BIOS_ERR, "Unknown lane count\n"); - } -} - -void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor, u8 link_bw) -{ - tegra_sor_write_field(sor, NV_SOR_CLK_CNTRL, - NV_SOR_CLK_CNTRL_DP_LINK_SPEED_MASK, - link_bw << NV_SOR_CLK_CNTRL_DP_LINK_SPEED_SHIFT); -} - -void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count) -{ - u32 reg_val; - - reg_val = tegra_sor_readl(sor, NV_SOR_DP_LINKCTL(sor->portnum)); - reg_val &= ~NV_SOR_DP_LINKCTL_LANECOUNT_MASK; - switch (lane_count) { - case 0: - break; - case 1: - reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_ONE; - break; - case 2: - reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_TWO; - break; - case 4: - reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_FOUR; - break; - default: - /* 0 should be handled earlier. */ - printk(BIOS_ERR, "dp: Invalid lane count %d\n", - lane_count); - return; - } - tegra_sor_writel(sor, NV_SOR_DP_LINKCTL(sor->portnum), reg_val); -} - -static void tegra_sor_enable_edp_clock(struct tegra_dc_sor_data *sor) -{ - sor_clock_start(); -} - -/* The SOR power sequencer does not work for t124/T132 so SW has to - go through the power sequence manually */ -/* Power up steps from spec: */ -/* STEP PDPORT PDPLL PDBG PLLVCOD PLLCAPD E_DPD PDCAL */ -/* 1 1 1 1 1 1 1 1 */ -/* 2 1 1 1 1 1 0 1 */ -/* 3 1 1 0 1 1 0 1 */ -/* 4 1 0 0 0 0 0 1 */ -/* 5 0 0 0 0 0 0 1 */ -static void tegra_dc_sor_power_up(struct tegra_dc_sor_data *sor, - int is_lvds) -{ - if (sor->power_is_up) - return; - - /* Set link bw */ - tegra_dc_sor_set_link_bandwidth(sor, - is_lvds ? NV_SOR_CLK_CNTRL_DP_LINK_SPEED_LVDS : - NV_SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62); - - /* step 1 */ - tegra_sor_write_field(sor, NV_SOR_PLL2, - NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK | /* PDPORT */ - NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK | /* PDBG */ - NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, /* PLLCAPD */ - NV_SOR_PLL2_AUX7_PORT_POWERDOWN_ENABLE | - NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_ENABLE | - NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_ENABLE); - tegra_sor_write_field(sor, NV_SOR_PLL0, - NV_SOR_PLL0_PWR_MASK | /* PDPLL */ - NV_SOR_PLL0_VCOPD_MASK, /* PLLVCOPD */ - NV_SOR_PLL0_PWR_OFF | - NV_SOR_PLL0_VCOPD_ASSERT); - tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), - NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN, /* PDCAL */ - NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERUP); - - /* step 2 */ - tegra_dc_sor_io_set_dpd(sor, 1); - udelay(15); - - /* step 3 */ - tegra_sor_write_field(sor, NV_SOR_PLL2, - NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK, - NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE); - udelay(25); - - /* step 4 */ - tegra_sor_write_field(sor, NV_SOR_PLL0, - NV_SOR_PLL0_PWR_MASK | /* PDPLL */ - NV_SOR_PLL0_VCOPD_MASK, /* PLLVCOPD */ - NV_SOR_PLL0_PWR_ON | NV_SOR_PLL0_VCOPD_RESCIND); - tegra_sor_write_field(sor, NV_SOR_PLL2, - NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, /* PLLCAPD */ - NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE); - udelay(225); - - /* step 5 */ - tegra_sor_write_field(sor, NV_SOR_PLL2, - NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK, /* PDPORT */ - NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE); - - sor->power_is_up = 1; -} - -#if DEBUG_SOR -static void dump_sor_reg(struct tegra_dc_sor_data *sor) -{ -#define DUMP_REG(a) printk(BIOS_INFO, "%-32s %03x %08x\n", \ - #a, a, tegra_sor_readl(sor, a)); - - DUMP_REG(NV_SOR_SUPER_STATE0); - DUMP_REG(NV_SOR_SUPER_STATE1); - DUMP_REG(NV_SOR_STATE0); - DUMP_REG(NV_SOR_STATE1); - DUMP_REG(NV_HEAD_STATE0(0)); - DUMP_REG(NV_HEAD_STATE0(1)); - DUMP_REG(NV_HEAD_STATE1(0)); - DUMP_REG(NV_HEAD_STATE1(1)); - DUMP_REG(NV_HEAD_STATE2(0)); - DUMP_REG(NV_HEAD_STATE2(1)); - DUMP_REG(NV_HEAD_STATE3(0)); - DUMP_REG(NV_HEAD_STATE3(1)); - DUMP_REG(NV_HEAD_STATE4(0)); - DUMP_REG(NV_HEAD_STATE4(1)); - DUMP_REG(NV_HEAD_STATE5(0)); - DUMP_REG(NV_HEAD_STATE5(1)); - DUMP_REG(NV_SOR_CRC_CNTRL); - DUMP_REG(NV_SOR_CLK_CNTRL); - DUMP_REG(NV_SOR_CAP); - DUMP_REG(NV_SOR_PWR); - DUMP_REG(NV_SOR_TEST); - DUMP_REG(NV_SOR_PLL0); - DUMP_REG(NV_SOR_PLL1); - DUMP_REG(NV_SOR_PLL2); - DUMP_REG(NV_SOR_PLL3); - DUMP_REG(NV_SOR_CSTM); - DUMP_REG(NV_SOR_LVDS); - DUMP_REG(NV_SOR_CRCA); - DUMP_REG(NV_SOR_CRCB); - DUMP_REG(NV_SOR_SEQ_CTL); - DUMP_REG(NV_SOR_LANE_SEQ_CTL); - DUMP_REG(NV_SOR_SEQ_INST(0)); - DUMP_REG(NV_SOR_SEQ_INST(1)); - DUMP_REG(NV_SOR_SEQ_INST(2)); - DUMP_REG(NV_SOR_SEQ_INST(3)); - DUMP_REG(NV_SOR_SEQ_INST(4)); - DUMP_REG(NV_SOR_SEQ_INST(5)); - DUMP_REG(NV_SOR_SEQ_INST(6)); - DUMP_REG(NV_SOR_SEQ_INST(7)); - DUMP_REG(NV_SOR_SEQ_INST(8)); - DUMP_REG(NV_SOR_PWM_DIV); - DUMP_REG(NV_SOR_PWM_CTL); - DUMP_REG(NV_SOR_MSCHECK); - DUMP_REG(NV_SOR_XBAR_CTRL); - DUMP_REG(NV_SOR_DP_LINKCTL(0)); - DUMP_REG(NV_SOR_DP_LINKCTL(1)); - DUMP_REG(NV_SOR_DC(0)); - DUMP_REG(NV_SOR_DC(1)); - DUMP_REG(NV_SOR_LANE_DRIVE_CURRENT(0)); - DUMP_REG(NV_SOR_PR(0)); - DUMP_REG(NV_SOR_LANE4_PREEMPHASIS(0)); - DUMP_REG(NV_SOR_POSTCURSOR(0)); - DUMP_REG(NV_SOR_DP_CONFIG(0)); - DUMP_REG(NV_SOR_DP_CONFIG(1)); - DUMP_REG(NV_SOR_DP_MN(0)); - DUMP_REG(NV_SOR_DP_MN(1)); - DUMP_REG(NV_SOR_DP_PADCTL(0)); - DUMP_REG(NV_SOR_DP_PADCTL(1)); - DUMP_REG(NV_SOR_DP_DEBUG(0)); - DUMP_REG(NV_SOR_DP_DEBUG(1)); - DUMP_REG(NV_SOR_DP_SPARE(0)); - DUMP_REG(NV_SOR_DP_SPARE(1)); - DUMP_REG(NV_SOR_DP_TPG); - - return; -} -#endif - -static void tegra_dc_sor_config_panel(struct tegra_dc_sor_data *sor, - int is_lvds) -{ - const struct tegra_dc *dc = sor->dc; - const struct tegra_dc_dp_data *dp = dc->out; - const struct tegra_dc_dp_link_config *link_cfg = &dp->link_cfg; - const struct soc_nvidia_tegra132_config *config = dc->config; - - const int head_num = 0; - u32 reg_val = NV_SOR_STATE1_ASY_OWNER_HEAD0 << head_num; - u32 vsync_end, hsync_end; - u32 vblank_end, hblank_end; - u32 vblank_start, hblank_start; - - reg_val |= is_lvds ? NV_SOR_STATE1_ASY_PROTOCOL_LVDS_CUSTOM : - NV_SOR_STATE1_ASY_PROTOCOL_DP_A; - reg_val |= NV_SOR_STATE1_ASY_SUBOWNER_NONE | - NV_SOR_STATE1_ASY_CRCMODE_COMPLETE_RASTER; - - reg_val |= NV_SOR_STATE1_ASY_HSYNCPOL_NEGATIVE_TRUE; - reg_val |= NV_SOR_STATE1_ASY_VSYNCPOL_NEGATIVE_TRUE; - reg_val |= (link_cfg->bits_per_pixel > 18) ? - NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_24_444 : - NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_18_444; - - tegra_sor_writel(sor, NV_SOR_STATE1, reg_val); - - /* Skipping programming NV_HEAD_STATE0, assuming: - interlacing: PROGRESSIVE, dynamic range: VESA, colorspace: RGB */ - - tegra_sor_writel(sor, NV_HEAD_STATE1(head_num), - vtotal(config) << NV_HEAD_STATE1_VTOTAL_SHIFT | - htotal(config) << NV_HEAD_STATE1_HTOTAL_SHIFT); - - vsync_end = config->vsync_width - 1; - hsync_end = config->hsync_width - 1; - tegra_sor_writel(sor, NV_HEAD_STATE2(head_num), - vsync_end << NV_HEAD_STATE2_VSYNC_END_SHIFT | - hsync_end << NV_HEAD_STATE2_HSYNC_END_SHIFT); - - vblank_end = vsync_end + config->vback_porch; - hblank_end = hsync_end + config->hback_porch; - tegra_sor_writel(sor, NV_HEAD_STATE3(head_num), - vblank_end << NV_HEAD_STATE3_VBLANK_END_SHIFT | - hblank_end << NV_HEAD_STATE3_HBLANK_END_SHIFT); - - vblank_start = vblank_end + config->yres; - hblank_start = hblank_end + config->xres; - tegra_sor_writel(sor, NV_HEAD_STATE4(head_num), - vblank_start << NV_HEAD_STATE4_VBLANK_START_SHIFT | - hblank_start << NV_HEAD_STATE4_HBLANK_START_SHIFT); - - /* TODO: adding interlace mode support */ - tegra_sor_writel(sor, NV_HEAD_STATE5(head_num), 0x1); - - tegra_sor_write_field(sor, NV_SOR_CSTM, - NV_SOR_CSTM_ROTCLK_DEFAULT_MASK | - NV_SOR_CSTM_LVDS_EN_ENABLE, - 2 << NV_SOR_CSTM_ROTCLK_SHIFT | - is_lvds ? NV_SOR_CSTM_LVDS_EN_ENABLE : - NV_SOR_CSTM_LVDS_EN_DISABLE); - - tegra_dc_sor_config_pwm(sor, 1024, 1024); -} - -static void tegra_dc_sor_enable_dc(struct tegra_dc_sor_data *sor) -{ - struct tegra_dc *dc = sor->dc; - struct display_controller *disp_ctrl = (void *)dc->base; - - u32 reg_val = READL(&disp_ctrl->cmd.state_access); - - WRITEL(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access); - WRITEL(VSYNC_H_POSITION(1), &disp_ctrl->disp.disp_timing_opt); - - /* Enable DC now - otherwise pure text console may not show. */ - WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd); - WRITEL(reg_val, &disp_ctrl->cmd.state_access); -} - -void tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor) -{ - const struct tegra_dc_dp_link_config *link_cfg = sor->link_cfg; - - tegra_sor_write_field(sor, NV_SOR_CLK_CNTRL, - NV_SOR_CLK_CNTRL_DP_CLK_SEL_MASK, - NV_SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK); - - tegra_sor_write_field(sor, NV_SOR_PLL2, - NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK, - NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE); - udelay(25); - - tegra_sor_write_field(sor, NV_SOR_PLL3, - NV_SOR_PLL3_PLLVDD_MODE_MASK, - NV_SOR_PLL3_PLLVDD_MODE_V3_3); - tegra_sor_writel(sor, NV_SOR_PLL0, - 0xf << NV_SOR_PLL0_ICHPMP_SHFIT | - 0x3 << NV_SOR_PLL0_VCOCAP_SHIFT | - NV_SOR_PLL0_PLLREG_LEVEL_V45 | - NV_SOR_PLL0_RESISTORSEL_EXT | - NV_SOR_PLL0_PWR_ON | NV_SOR_PLL0_VCOPD_RESCIND); - tegra_sor_write_field(sor, NV_SOR_PLL2, - NV_SOR_PLL2_AUX1_SEQ_MASK | NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE | - NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, - NV_SOR_PLL2_AUX1_SEQ_PLLCAPPD_OVERRIDE | - NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE | - NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE); - tegra_sor_writel(sor, NV_SOR_PLL1, - NV_SOR_PLL1_TERM_COMPOUT_HIGH | NV_SOR_PLL1_TMDS_TERM_ENABLE); - - if (tegra_dc_sor_poll_register(sor, NV_SOR_PLL2, - NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, - NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE, - 100, TEGRA_SOR_TIMEOUT_MS * 1000)) { - printk(BIOS_ERR, "DP failed to lock PLL\n"); - return; - } - - tegra_sor_write_field(sor, NV_SOR_PLL2, - NV_SOR_PLL2_AUX2_MASK | NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK, - NV_SOR_PLL2_AUX2_OVERRIDE_POWERDOWN | - NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE); - - tegra_dc_sor_power_up(sor, 0); - - /* re-enable SOR clock */ - tegra_sor_enable_edp_clock(sor); /* select pll_dp as clock source */ - - /* Power up lanes */ - tegra_dc_sor_power_dplanes(sor, link_cfg->lane_count, 1); - - tegra_dc_sor_set_dp_mode(sor, link_cfg); - -} - -void tegra_dc_sor_attach(struct tegra_dc_sor_data *sor) -{ - u32 reg_val; - struct display_controller *disp_ctrl = (void *)sor->dc->base; - - tegra_dc_sor_enable_dc(sor); - tegra_dc_sor_config_panel(sor, 0); - - WRITEL(0x9f00, &disp_ctrl->cmd.state_ctrl); - WRITEL(0x9f, &disp_ctrl->cmd.state_ctrl); - - WRITEL(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | - PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE, - &disp_ctrl->cmd.disp_pow_ctrl); - - reg_val = tegra_sor_readl(sor, NV_SOR_TEST); - if (reg_val & NV_SOR_TEST_ATTACHED_TRUE) - return; - - tegra_sor_writel(sor, NV_SOR_SUPER_STATE1, - NV_SOR_SUPER_STATE1_ATTACHED_NO); - - /* - * Enable display2sor clock at least 2 cycles before DC start, - * to clear sor internal valid signal. - */ - - /* Stop dc for 3 cycles */ - WRITEL(0, &disp_ctrl->disp.disp_win_opt); - WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl); - udelay(FRAME_IN_MS * 1000 * 3); - - /* Attach head */ - tegra_dc_sor_update(sor); - tegra_sor_writel(sor, NV_SOR_SUPER_STATE1, - NV_SOR_SUPER_STATE1_ATTACHED_YES); - tegra_sor_writel(sor, NV_SOR_SUPER_STATE1, - NV_SOR_SUPER_STATE1_ATTACHED_YES | - NV_SOR_SUPER_STATE1_ASY_HEAD_OP_AWAKE | - NV_SOR_SUPER_STATE1_ASY_ORMODE_NORMAL); - tegra_dc_sor_super_update(sor); - - /* wait for another 5 cycles */ - udelay(FRAME_IN_MS * 1000 * 5); - - /* Re-enable dc */ - WRITEL(READ_MUX_ACTIVE | WRITE_MUX_ACTIVE, - &disp_ctrl->cmd.state_access); - WRITEL(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt); - - WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd); - WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl); - - if (tegra_dc_sor_poll_register(sor, NV_SOR_TEST, - NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK, - NV_SOR_TEST_ACT_HEAD_OPMODE_AWAKE, - 100, TEGRA_SOR_ATTACH_TIMEOUT_MS * 1000)) - printk(BIOS_ERR, "dc timeout waiting for OPMOD = AWAKE\n"); - else - printk(BIOS_INFO, "%s: sor is attached\n", __func__); - -#if DEBUG_SOR - dump_sor_reg(sor); -#endif -} - -void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor, - const struct tegra_dc_dp_link_config *link_cfg) -{ - tegra_sor_writel(sor, NV_SOR_LANE_DRIVE_CURRENT(sor->portnum), - link_cfg->drive_current); - tegra_sor_writel(sor, NV_SOR_PR(sor->portnum), - link_cfg->preemphasis); - tegra_sor_writel(sor, NV_SOR_POSTCURSOR(sor->portnum), - link_cfg->postcursor); - tegra_sor_writel(sor, NV_SOR_LVDS, 0); - - tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw); - tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count); - - tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), - NV_SOR_DP_PADCTL_TX_PU_ENABLE | - NV_SOR_DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK, - NV_SOR_DP_PADCTL_TX_PU_ENABLE | - 2 << NV_SOR_DP_PADCTL_TX_PU_VALUE_SHIFT); - - /* Precharge */ - tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), - 0xf0, 0xf0); - udelay(20); - - tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), - 0xf0, 0x0); -} - -void tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor) -{ - u32 drive_current = 0; - u32 pre_emphasis = 0; - - /* Set to a known-good pre-calibrated setting */ - switch (sor->link_cfg->link_bw) { - case SOR_LINK_SPEED_G1_62: - case SOR_LINK_SPEED_G2_7: - drive_current = 0x13131313; - pre_emphasis = 0; - break; - case SOR_LINK_SPEED_G5_4: - printk(BIOS_WARNING, "T124/T132 does not support 5.4G link" - " clock.\n"); - default: - printk(BIOS_WARNING, "Invalid sor link bandwidth: %d\n", - sor->link_cfg->link_bw); - return; - } - - tegra_sor_writel(sor, NV_SOR_LANE_DRIVE_CURRENT(sor->portnum), - drive_current); - tegra_sor_writel(sor, NV_SOR_PR(sor->portnum), pre_emphasis); -} - -void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor) -{ - u32 pad_ctrl = 0; - int err = 0; - - switch (sor->link_cfg->lane_count) { - case 4: - pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO | - NV_SOR_DP_PADCTL_PD_TXD_1_NO | - NV_SOR_DP_PADCTL_PD_TXD_2_NO | - NV_SOR_DP_PADCTL_PD_TXD_3_NO); - break; - case 2: - pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO | - NV_SOR_DP_PADCTL_PD_TXD_1_NO | - NV_SOR_DP_PADCTL_PD_TXD_2_YES | - NV_SOR_DP_PADCTL_PD_TXD_3_YES); - break; - case 1: - pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO | - NV_SOR_DP_PADCTL_PD_TXD_1_YES | - NV_SOR_DP_PADCTL_PD_TXD_2_YES | - NV_SOR_DP_PADCTL_PD_TXD_3_YES); - break; - default: - printk(BIOS_ERR, "Invalid sor lane count: %u\n", - sor->link_cfg->lane_count); - return; - } - - pad_ctrl |= NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN; - tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), pad_ctrl); - - err = tegra_dc_sor_enable_lane_sequencer(sor, 0, 0); - if (err) { - printk(BIOS_ERR, - "Wait for lane power down failed: %d\n", err); - return; - } -} - -void tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor) -{ - const struct tegra_dc_dp_link_config *cfg = sor->link_cfg; - u32 val = 0; - - switch (cfg->lane_count) { - case 4: - val |= (NV_SOR_DP_PADCTL_PD_TXD_3_NO | - NV_SOR_DP_PADCTL_PD_TXD_2_NO); - /* fall through */ - case 2: - val |= NV_SOR_DP_PADCTL_PD_TXD_1_NO; - /* fall through */ - case 1: - val |= NV_SOR_DP_PADCTL_PD_TXD_0_NO; - break; - default: - printk(BIOS_ERR, - "dp: invalid lane number %d\n", cfg->lane_count); - return; - } - - tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), - (0xf << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT), - (val << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT)); - udelay(100); - tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), - (0xf << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT), 0); -} - -static u32 tegra_dc_poll_register(void *reg, - u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_us) -{ - u32 temp = timeout_us; - u32 reg_val = 0; - - do { - udelay(poll_interval_us); - reg_val = READL(reg); - if (timeout_us > poll_interval_us) - timeout_us -= poll_interval_us; - else - break; - } while ((reg_val & mask) != exp_val); - - if ((reg_val & mask) == exp_val) - return 0; /* success */ - - return temp; -} - -static void tegra_dc_sor_general_act(struct display_controller *disp_ctrl) -{ - WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl); - - if (tegra_dc_poll_register(&disp_ctrl->cmd.state_ctrl, - GENERAL_ACT_REQ, 0, 100, - TEGRA_DC_POLL_TIMEOUT_MS*1000)) - printk(BIOS_ERR, - "dc timeout waiting for DC to stop\n"); -} - -static struct tegra_dc_mode min_mode = { - .h_ref_to_sync = 0, - .v_ref_to_sync = 1, - .h_sync_width = 1, - .v_sync_width = 1, - .h_back_porch = 20, - .v_back_porch = 0, - .h_active = 16, - .v_active = 16, - .h_front_porch = 1, - .v_front_porch = 2, -}; - -/* Disable windows and set minimum raster timings */ -static void -tegra_dc_sor_disable_win_short_raster(struct display_controller *disp_ctrl, - int *dc_reg_ctx) -{ - int selected_windows, i; - - selected_windows = READL(&disp_ctrl->cmd.disp_win_header); - - /* Store and clear window options */ - for (i = 0; i < DC_N_WINDOWS; ++i) { - WRITEL(WINDOW_A_SELECT << i, &disp_ctrl->cmd.disp_win_header); - dc_reg_ctx[i] = READL(&disp_ctrl->win.win_opt); - WRITEL(0, &disp_ctrl->win.win_opt); - WRITEL(WIN_A_ACT_REQ << i, &disp_ctrl->cmd.state_ctrl); - } - - WRITEL(selected_windows, &disp_ctrl->cmd.disp_win_header); - - /* Store current raster timings and set minimum timings */ - dc_reg_ctx[i++] = READL(&disp_ctrl->disp.ref_to_sync); - WRITEL(min_mode.h_ref_to_sync | (min_mode.v_ref_to_sync << 16), - &disp_ctrl->disp.ref_to_sync); - - dc_reg_ctx[i++] = READL(&disp_ctrl->disp.sync_width); - WRITEL(min_mode.h_sync_width | (min_mode.v_sync_width << 16), - &disp_ctrl->disp.sync_width); - - dc_reg_ctx[i++] = READL(&disp_ctrl->disp.back_porch); - WRITEL(min_mode.h_back_porch | - min_mode.v_back_porch << 16, - &disp_ctrl->disp.back_porch); - - dc_reg_ctx[i++] = READL(&disp_ctrl->disp.front_porch); - WRITEL(min_mode.h_front_porch | - min_mode.v_front_porch << 16, - &disp_ctrl->disp.front_porch); - - dc_reg_ctx[i++] = READL(&disp_ctrl->disp.disp_active); - WRITEL(min_mode.h_active | (min_mode.v_active << 16), - &disp_ctrl->disp.disp_active); - - WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl); -} - -/* Restore previous windows status and raster timings */ -static void -tegra_dc_sor_restore_win_and_raster(struct display_controller *disp_ctrl, - int *dc_reg_ctx) -{ - int selected_windows, i; - - selected_windows = READL(&disp_ctrl->cmd.disp_win_header); - - for (i = 0; i < DC_N_WINDOWS; ++i) { - WRITEL(WINDOW_A_SELECT << i, &disp_ctrl->cmd.disp_win_header); - WRITEL(dc_reg_ctx[i], &disp_ctrl->win.win_opt); - WRITEL(WIN_A_ACT_REQ << i, &disp_ctrl->cmd.state_ctrl); - } - - WRITEL(selected_windows, &disp_ctrl->cmd.disp_win_header); - - WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.ref_to_sync); - WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.sync_width); - WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.back_porch); - WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.front_porch); - WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.disp_active); - - WRITEL(GENERAL_UPDATE, &disp_ctrl->cmd.state_ctrl); -} - -static void tegra_dc_sor_enable_sor(struct tegra_dc_sor_data *sor, int enable) -{ - struct display_controller *disp_ctrl = (void *)sor->dc->base; - u32 reg_val = READL(&disp_ctrl->disp.disp_win_opt); - - reg_val = enable ? reg_val | SOR_ENABLE : reg_val & ~SOR_ENABLE; - WRITEL(reg_val, &disp_ctrl->disp.disp_win_opt); -} - -void tegra_dc_detach(struct tegra_dc_sor_data *sor) -{ - struct display_controller *disp_ctrl = (void *)sor->dc->base; - int dc_reg_ctx[DC_N_WINDOWS + 5]; - unsigned long dc_int_mask; - - /* Sleep mode */ - tegra_sor_writel(sor, NV_SOR_SUPER_STATE1, - NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SLEEP | - NV_SOR_SUPER_STATE1_ASY_ORMODE_SAFE | - NV_SOR_SUPER_STATE1_ATTACHED_YES); - tegra_dc_sor_super_update(sor); - - tegra_dc_sor_disable_win_short_raster(disp_ctrl, dc_reg_ctx); - - if (tegra_dc_sor_poll_register(sor, NV_SOR_TEST, - NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK, - NV_SOR_TEST_ACT_HEAD_OPMODE_SLEEP, - 100, TEGRA_SOR_ATTACH_TIMEOUT_MS*1000)) { - printk(BIOS_ERR, - "dc timeout waiting for OPMOD = SLEEP\n"); - } - - tegra_sor_writel(sor, NV_SOR_SUPER_STATE1, - NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SLEEP | - NV_SOR_SUPER_STATE1_ASY_ORMODE_SAFE | - NV_SOR_SUPER_STATE1_ATTACHED_NO); - - /* Mask DC interrupts during the 2 dummy frames required for detach */ - dc_int_mask = READL(&disp_ctrl->cmd.int_mask); - WRITEL(0, &disp_ctrl->cmd.int_mask); - - /* Stop DC->SOR path */ - tegra_dc_sor_enable_sor(sor, 0); - tegra_dc_sor_general_act(disp_ctrl); - - /* Stop DC */ - WRITEL(DISP_CTRL_MODE_STOP, &disp_ctrl->cmd.disp_cmd); - tegra_dc_sor_general_act(disp_ctrl); - - tegra_dc_sor_restore_win_and_raster(disp_ctrl, dc_reg_ctx); - - WRITEL(dc_int_mask, &disp_ctrl->cmd.int_mask); -} |