blob: 72e1eb4bc8ae42029b2ac4e686186f5a3fd68041 [file] [log] [blame]
Angel Ponsa2ee7612020-04-04 18:51:15 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
3
Patrick Georgi40a3e322015-06-22 19:41:29 +02004/*
5 * drivers/video/tegra/dc/sor.c
Patrick Georgi40a3e322015-06-22 19:41:29 +02006 */
7
8#include <console/console.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +02009#include <stdint.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +020010#include <delay.h>
11#include <soc/addressmap.h>
12#include <device/device.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +020013#include <boot/tables.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +020014#include <soc/nvidia/tegra/dc.h>
15#include <soc/nvidia/tegra/types.h>
16#include <soc/sor.h>
17#include <soc/nvidia/tegra/displayport.h>
18#include <soc/clk_rst.h>
19#include <soc/clock.h>
20#include "chip.h"
21#include <soc/display.h>
22
23#define DEBUG_SOR 0
24
25#define APBDEV_PMC_DPD_SAMPLE (0x20)
26#define APBDEV_PMC_DPD_SAMPLE_ON_DISABLE (0)
27#define APBDEV_PMC_DPD_SAMPLE_ON_ENABLE (1)
28#define APBDEV_PMC_SEL_DPD_TIM (0x1c8)
29#define APBDEV_PMC_SEL_DPD_TIM_SEL_DPD_TIM_DEFAULT (0x7f)
30#define APBDEV_PMC_IO_DPD2_REQ (0x1c0)
31#define APBDEV_PMC_IO_DPD2_REQ_LVDS_SHIFT (25)
32#define APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF (0 << 25)
33#define APBDEV_PMC_IO_DPD2_REQ_LVDS_ON (1 << 25)
34#define APBDEV_PMC_IO_DPD2_REQ_CODE_SHIFT (30)
35#define APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK (0x3 << 30)
36#define APBDEV_PMC_IO_DPD2_REQ_CODE_IDLE (0 << 30)
37#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF (1 << 30)
38#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON (2 << 30)
39#define APBDEV_PMC_IO_DPD2_STATUS (0x1c4)
40#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_SHIFT (25)
41#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_OFF (0 << 25)
42#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON (1 << 25)
43
44#define DC_N_WINDOWS 5
45
46static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg)
47{
48 void *addr = sor->base + (u32) (reg << 2);
49 u32 reg_val = READL(addr);
50 return reg_val;
51}
52
53static inline void tegra_sor_writel(struct tegra_dc_sor_data *sor,
54 u32 reg, u32 val)
55{
56 void *addr = sor->base + (u32) (reg << 2);
57 WRITEL(val, addr);
58}
59
60static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor,
61 u32 reg, u32 mask, u32 val)
62{
63 u32 reg_val = tegra_sor_readl(sor, reg);
64 reg_val &= ~mask;
65 reg_val |= val;
66 tegra_sor_writel(sor, reg, reg_val);
67}
68
69void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor)
70{
71 tegra_sor_write_field(sor,
72 NV_SOR_DP_PADCTL(sor->portnum),
73 NV_SOR_DP_PADCTL_TX_PU_MASK,
74 NV_SOR_DP_PADCTL_TX_PU_DISABLE);
75}
76
77void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask,
78 u32 pe_reg, u32 vs_reg, u32 pc_reg, u8 pc_supported)
79{
80 tegra_sor_write_field(sor, NV_SOR_PR(sor->portnum),
81 mask, pe_reg);
82 tegra_sor_write_field(sor, NV_SOR_DC(sor->portnum),
83 mask, vs_reg);
84 if (pc_supported) {
85 tegra_sor_write_field(
86 sor, NV_SOR_POSTCURSOR(sor->portnum),
87 mask, pc_reg);
88 }
89}
90
91static u32 tegra_dc_sor_poll_register(struct tegra_dc_sor_data *sor,
92 u32 reg, u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_us)
93{
94 u32 temp = timeout_us;
95 u32 reg_val = 0;
96
97 do {
98 udelay(poll_interval_us);
99 reg_val = tegra_sor_readl(sor, reg);
100 if (timeout_us > poll_interval_us)
101 timeout_us -= poll_interval_us;
102 else
103 break;
104 } while ((reg_val & mask) != exp_val);
105
106 if ((reg_val & mask) == exp_val)
107 return 0; /* success */
108 printk(BIOS_ERR,
109 "sor_poll_register 0x%x: timeout, "
110 "(reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n",
111 reg, reg_val, mask, exp_val);
112
113 return temp;
114}
115
116int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd)
117{
118 u32 reg_val;
119 u32 orig_val;
120
121 orig_val = tegra_sor_readl(sor, NV_SOR_PWR);
122
123 reg_val = pu_pd ? NV_SOR_PWR_NORMAL_STATE_PU :
124 NV_SOR_PWR_NORMAL_STATE_PD; /* normal state only */
125
126 if (reg_val == orig_val)
127 return 0; /* No update needed */
128
129 reg_val |= NV_SOR_PWR_SETTING_NEW_TRIGGER;
130 tegra_sor_writel(sor, NV_SOR_PWR, reg_val);
131
132 /* Poll to confirm it is done */
133 if (tegra_dc_sor_poll_register(sor, NV_SOR_PWR,
134 NV_SOR_PWR_SETTING_NEW_DEFAULT_MASK,
135 NV_SOR_PWR_SETTING_NEW_DONE,
136 100, TEGRA_SOR_TIMEOUT_MS * 1000)) {
137 printk(BIOS_ERR,
138 "dc timeout waiting for SOR_PWR = NEW_DONE\n");
139 return -EFAULT;
140 }
141 return 0;
142}
143
144void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena,
145 u8 training_pattern, const struct tegra_dc_dp_link_config *link_cfg)
146{
147 u32 reg_val;
148
149 reg_val = tegra_sor_readl(sor, NV_SOR_DP_LINKCTL(sor->portnum));
150
151 if (ena)
152 reg_val |= NV_SOR_DP_LINKCTL_ENABLE_YES;
153 else
154 reg_val &= NV_SOR_DP_LINKCTL_ENABLE_NO;
155
156 reg_val &= ~NV_SOR_DP_LINKCTL_TUSIZE_MASK;
157 reg_val |= (link_cfg->tu_size << NV_SOR_DP_LINKCTL_TUSIZE_SHIFT);
158
159 if (link_cfg->enhanced_framing)
160 reg_val |= NV_SOR_DP_LINKCTL_ENHANCEDFRAME_ENABLE;
161
162 tegra_sor_writel(sor, NV_SOR_DP_LINKCTL(sor->portnum), reg_val);
163
164 switch (training_pattern) {
165 case training_pattern_1:
166 tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x41414141);
167 break;
168 case training_pattern_2:
169 case training_pattern_3:
170 reg_val = (link_cfg->link_bw == SOR_LINK_SPEED_G5_4) ?
171 0x43434343 : 0x42424242;
172 tegra_sor_writel(sor, NV_SOR_DP_TPG, reg_val);
173 break;
174 default:
175 tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x50505050);
176 break;
177 }
178}
179
180static int tegra_dc_sor_enable_lane_sequencer(struct tegra_dc_sor_data *sor,
181 int pu, int is_lvds)
182{
183 u32 reg_val;
184
185 /* SOR lane sequencer */
186 if (pu)
187 reg_val = NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER |
188 NV_SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
189 NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PU;
190 else
191 reg_val = NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER |
192 NV_SOR_LANE_SEQ_CTL_SEQUENCE_UP |
193 NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PD;
194
195 if (is_lvds)
196 reg_val |= 15 << NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT;
197 else
198 reg_val |= 1 << NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT;
199
200 tegra_sor_writel(sor, NV_SOR_LANE_SEQ_CTL, reg_val);
201
202 if (tegra_dc_sor_poll_register(sor, NV_SOR_LANE_SEQ_CTL,
203 NV_SOR_LANE_SEQ_CTL_SETTING_MASK,
204 NV_SOR_LANE_SEQ_CTL_SETTING_NEW_DONE,
205 100, TEGRA_SOR_TIMEOUT_MS*1000)) {
206 printk(BIOS_ERR,
207 "dp: timeout while waiting for SOR lane sequencer "
208 "to power down langes\n");
209 return -1;
210 }
211 return 0;
212}
213
214static int tegra_dc_sor_power_dplanes(struct tegra_dc_sor_data *sor,
215 u32 lane_count, int pu)
216{
217 u32 reg_val;
218
219 reg_val = tegra_sor_readl(sor, NV_SOR_DP_PADCTL(sor->portnum));
220
221 if (pu) {
222 switch (lane_count) {
223 case 4:
224 reg_val |= (NV_SOR_DP_PADCTL_PD_TXD_3_NO |
225 NV_SOR_DP_PADCTL_PD_TXD_2_NO);
226 /* fall through */
227 case 2:
228 reg_val |= NV_SOR_DP_PADCTL_PD_TXD_1_NO;
229 case 1:
230 reg_val |= NV_SOR_DP_PADCTL_PD_TXD_0_NO;
231 break;
232 default:
233 printk(BIOS_ERR,
234 "dp: invalid lane number %d\n", lane_count);
235 return -1;
236 }
237
238 tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), reg_val);
239 tegra_dc_sor_set_lane_count(sor, lane_count);
240 }
241 return tegra_dc_sor_enable_lane_sequencer(sor, pu, 0);
242}
243
244void tegra_dc_sor_set_panel_power(struct tegra_dc_sor_data *sor,
245 int power_up)
246{
247 u32 reg_val;
248
249 reg_val = tegra_sor_readl(sor, NV_SOR_DP_PADCTL(sor->portnum));
250
251 if (power_up)
252 reg_val &= ~NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN;
253 else
254 reg_val |= NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN;
255
256 tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), reg_val);
257}
258
259static void tegra_dc_sor_config_pwm(struct tegra_dc_sor_data *sor, u32 pwm_div,
260 u32 pwm_dutycycle)
261{
262 tegra_sor_writel(sor, NV_SOR_PWM_DIV, pwm_div);
263 tegra_sor_writel(sor, NV_SOR_PWM_CTL,
264 (pwm_dutycycle & NV_SOR_PWM_CTL_DUTY_CYCLE_MASK) |
265 NV_SOR_PWM_CTL_SETTING_NEW_TRIGGER);
266
267 if (tegra_dc_sor_poll_register(sor, NV_SOR_PWM_CTL,
268 NV_SOR_PWM_CTL_SETTING_NEW_SHIFT,
269 NV_SOR_PWM_CTL_SETTING_NEW_DONE,
270 100, TEGRA_SOR_TIMEOUT_MS * 1000)) {
271 printk(BIOS_ERR,
272 "dp: timeout while waiting for SOR PWM setting\n");
273 }
274}
275
276static void tegra_dc_sor_set_dp_mode(struct tegra_dc_sor_data *sor,
277 const struct tegra_dc_dp_link_config *link_cfg)
278{
279 u32 reg_val;
280
281 tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw);
282
283 tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_none, link_cfg);
284 reg_val = tegra_sor_readl(sor, NV_SOR_DP_CONFIG(sor->portnum));
285 reg_val &= ~NV_SOR_DP_CONFIG_WATERMARK_MASK;
286 reg_val |= link_cfg->watermark;
287 reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_MASK;
288 reg_val |= (link_cfg->active_count <<
289 NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_SHIFT);
290 reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_MASK;
291 reg_val |= (link_cfg->active_frac <<
292 NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_SHIFT);
293 if (link_cfg->activepolarity)
294 reg_val |= NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE;
295 else
296 reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE;
297 reg_val |= (NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE |
298 NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE);
299
300 tegra_sor_writel(sor, NV_SOR_DP_CONFIG(sor->portnum), reg_val);
301
302 /* program h/vblank sym */
303 tegra_sor_write_field(sor, NV_SOR_DP_AUDIO_HBLANK_SYMBOLS,
304 NV_SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK, link_cfg->hblank_sym);
305
306 tegra_sor_write_field(sor, NV_SOR_DP_AUDIO_VBLANK_SYMBOLS,
307 NV_SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK, link_cfg->vblank_sym);
308}
309
310static inline void tegra_dc_sor_super_update(struct tegra_dc_sor_data *sor)
311{
312 tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 0);
313 tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 1);
314 tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 0);
315}
316
317static inline void tegra_dc_sor_update(struct tegra_dc_sor_data *sor)
318{
319 tegra_sor_writel(sor, NV_SOR_STATE0, 0);
320 tegra_sor_writel(sor, NV_SOR_STATE0, 1);
321 tegra_sor_writel(sor, NV_SOR_STATE0, 0);
322}
323
324static void tegra_dc_sor_io_set_dpd(struct tegra_dc_sor_data *sor, int up)
325{
326 u32 reg_val;
327 void *pmc_base = sor->pmc_base;
328
329 if (up) {
330 WRITEL(APBDEV_PMC_DPD_SAMPLE_ON_ENABLE,
331 pmc_base + APBDEV_PMC_DPD_SAMPLE);
332 WRITEL(10, pmc_base + APBDEV_PMC_SEL_DPD_TIM);
333 }
334
335 reg_val = READL(pmc_base + APBDEV_PMC_IO_DPD2_REQ);
336 reg_val &= ~(APBDEV_PMC_IO_DPD2_REQ_LVDS_ON ||
337 APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK);
338
339 reg_val = up ? APBDEV_PMC_IO_DPD2_REQ_LVDS_ON |
340 APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF :
341 APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF |
342 APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON;
343
344 WRITEL(reg_val, pmc_base + APBDEV_PMC_IO_DPD2_REQ);
345
346 /* Polling */
347 u32 temp = 10*1000;
348 do {
349 udelay(20);
350 reg_val = READL(pmc_base + APBDEV_PMC_IO_DPD2_STATUS);
351 if (temp > 20)
352 temp -= 20;
353 else
354 break;
355 } while ((reg_val & APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON) != 0);
356
357 if ((reg_val & APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON) != 0)
358 printk(BIOS_ERR,
359 "PMC_IO_DPD2 polling failed (0x%x)\n", reg_val);
360
361 if (up)
362 WRITEL(APBDEV_PMC_DPD_SAMPLE_ON_DISABLE,
363 pmc_base + APBDEV_PMC_DPD_SAMPLE);
364}
365
366void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int)
367{
368 u32 reg_val;
369
370 reg_val = tegra_sor_readl(sor, NV_SOR_DP_SPARE(sor->portnum));
371 if (is_int)
372 reg_val |= NV_SOR_DP_SPARE_PANEL_INTERNAL;
373 else
374 reg_val &= ~NV_SOR_DP_SPARE_PANEL_INTERNAL;
375
376 reg_val |= NV_SOR_DP_SPARE_SOR_CLK_SEL_MACRO_SORCLK |
377 NV_SOR_DP_SPARE_SEQ_ENABLE_YES;
378 tegra_sor_writel(sor, NV_SOR_DP_SPARE(sor->portnum), reg_val);
379}
380
381void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw,
382 u8 *lane_count)
383{
384 u32 reg_val;
385
386 reg_val = tegra_sor_readl(sor, NV_SOR_CLK_CNTRL);
387 *link_bw = (reg_val & NV_SOR_CLK_CNTRL_DP_LINK_SPEED_MASK)
388 >> NV_SOR_CLK_CNTRL_DP_LINK_SPEED_SHIFT;
389 reg_val = tegra_sor_readl(sor,
390 NV_SOR_DP_LINKCTL(sor->portnum));
391
392 switch (reg_val & NV_SOR_DP_LINKCTL_LANECOUNT_MASK) {
393 case NV_SOR_DP_LINKCTL_LANECOUNT_ZERO:
394 *lane_count = 0;
395 break;
396 case NV_SOR_DP_LINKCTL_LANECOUNT_ONE:
397 *lane_count = 1;
398 break;
399 case NV_SOR_DP_LINKCTL_LANECOUNT_TWO:
400 *lane_count = 2;
401 break;
402 case NV_SOR_DP_LINKCTL_LANECOUNT_FOUR:
403 *lane_count = 4;
404 break;
405 default:
406 printk(BIOS_ERR, "Unknown lane count\n");
407 }
408}
409
410void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor, u8 link_bw)
411{
412 tegra_sor_write_field(sor, NV_SOR_CLK_CNTRL,
413 NV_SOR_CLK_CNTRL_DP_LINK_SPEED_MASK,
414 link_bw << NV_SOR_CLK_CNTRL_DP_LINK_SPEED_SHIFT);
415}
416
417void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count)
418{
419 u32 reg_val;
420
421 reg_val = tegra_sor_readl(sor, NV_SOR_DP_LINKCTL(sor->portnum));
422 reg_val &= ~NV_SOR_DP_LINKCTL_LANECOUNT_MASK;
423 switch (lane_count) {
424 case 0:
425 break;
426 case 1:
427 reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_ONE;
428 break;
429 case 2:
430 reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_TWO;
431 break;
432 case 4:
433 reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_FOUR;
434 break;
435 default:
436 /* 0 should be handled earlier. */
437 printk(BIOS_ERR, "dp: Invalid lane count %d\n",
438 lane_count);
439 return;
440 }
441 tegra_sor_writel(sor, NV_SOR_DP_LINKCTL(sor->portnum), reg_val);
442}
443
444static void tegra_sor_enable_edp_clock(struct tegra_dc_sor_data *sor)
445{
446 sor_clock_start();
447}
448
449/* The SOR power sequencer does not work for t1xx so SW has to
450 go through the power sequence manually */
451/* Power up steps from spec: */
452/* STEP PDPORT PDPLL PDBG PLLVCOD PLLCAPD E_DPD PDCAL */
453/* 1 1 1 1 1 1 1 1 */
454/* 2 1 1 1 1 1 0 1 */
455/* 3 1 1 0 1 1 0 1 */
456/* 4 1 0 0 0 0 0 1 */
457/* 5 0 0 0 0 0 0 1 */
458static void tegra_dc_sor_power_up(struct tegra_dc_sor_data *sor,
459 int is_lvds)
460{
461 if (sor->power_is_up)
462 return;
463
464 /* Set link bw */
465 tegra_dc_sor_set_link_bandwidth(sor,
466 is_lvds ? NV_SOR_CLK_CNTRL_DP_LINK_SPEED_LVDS :
467 NV_SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62);
468
469 /* step 1 */
470 tegra_sor_write_field(sor, NV_SOR_PLL2,
471 NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK | /* PDPORT */
472 NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK | /* PDBG */
473 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, /* PLLCAPD */
474 NV_SOR_PLL2_AUX7_PORT_POWERDOWN_ENABLE |
475 NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_ENABLE |
476 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_ENABLE);
477 tegra_sor_write_field(sor, NV_SOR_PLL0,
478 NV_SOR_PLL0_PWR_MASK | /* PDPLL */
479 NV_SOR_PLL0_VCOPD_MASK, /* PLLVCOPD */
480 NV_SOR_PLL0_PWR_OFF |
481 NV_SOR_PLL0_VCOPD_ASSERT);
482 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
483 NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN, /* PDCAL */
484 NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERUP);
485
486 /* step 2 */
487 tegra_dc_sor_io_set_dpd(sor, 1);
488 udelay(15);
489
490 /* step 3 */
491 tegra_sor_write_field(sor, NV_SOR_PLL2,
492 NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK,
493 NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE);
494 udelay(25);
495
496 /* step 4 */
497 tegra_sor_write_field(sor, NV_SOR_PLL0,
498 NV_SOR_PLL0_PWR_MASK | /* PDPLL */
499 NV_SOR_PLL0_VCOPD_MASK, /* PLLVCOPD */
500 NV_SOR_PLL0_PWR_ON | NV_SOR_PLL0_VCOPD_RESCIND);
501 tegra_sor_write_field(sor, NV_SOR_PLL2,
502 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, /* PLLCAPD */
503 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE);
504 udelay(225);
505
506 /* step 5 */
507 tegra_sor_write_field(sor, NV_SOR_PLL2,
508 NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK, /* PDPORT */
509 NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE);
510
511 sor->power_is_up = 1;
512}
513
514#if DEBUG_SOR
515static void dump_sor_reg(struct tegra_dc_sor_data *sor)
516{
517#define DUMP_REG(a) printk(BIOS_INFO, "%-32s %03x %08x\n", \
518 #a, a, tegra_sor_readl(sor, a));
519
520 DUMP_REG(NV_SOR_SUPER_STATE0);
521 DUMP_REG(NV_SOR_SUPER_STATE1);
522 DUMP_REG(NV_SOR_STATE0);
523 DUMP_REG(NV_SOR_STATE1);
524 DUMP_REG(NV_HEAD_STATE0(0));
525 DUMP_REG(NV_HEAD_STATE0(1));
526 DUMP_REG(NV_HEAD_STATE1(0));
527 DUMP_REG(NV_HEAD_STATE1(1));
528 DUMP_REG(NV_HEAD_STATE2(0));
529 DUMP_REG(NV_HEAD_STATE2(1));
530 DUMP_REG(NV_HEAD_STATE3(0));
531 DUMP_REG(NV_HEAD_STATE3(1));
532 DUMP_REG(NV_HEAD_STATE4(0));
533 DUMP_REG(NV_HEAD_STATE4(1));
534 DUMP_REG(NV_HEAD_STATE5(0));
535 DUMP_REG(NV_HEAD_STATE5(1));
536 DUMP_REG(NV_SOR_CRC_CNTRL);
537 DUMP_REG(NV_SOR_CLK_CNTRL);
538 DUMP_REG(NV_SOR_CAP);
539 DUMP_REG(NV_SOR_PWR);
540 DUMP_REG(NV_SOR_TEST);
541 DUMP_REG(NV_SOR_PLL0);
542 DUMP_REG(NV_SOR_PLL1);
543 DUMP_REG(NV_SOR_PLL2);
544 DUMP_REG(NV_SOR_PLL3);
545 DUMP_REG(NV_SOR_CSTM);
546 DUMP_REG(NV_SOR_LVDS);
547 DUMP_REG(NV_SOR_CRCA);
548 DUMP_REG(NV_SOR_CRCB);
549 DUMP_REG(NV_SOR_SEQ_CTL);
550 DUMP_REG(NV_SOR_LANE_SEQ_CTL);
551 DUMP_REG(NV_SOR_SEQ_INST(0));
552 DUMP_REG(NV_SOR_SEQ_INST(1));
553 DUMP_REG(NV_SOR_SEQ_INST(2));
554 DUMP_REG(NV_SOR_SEQ_INST(3));
555 DUMP_REG(NV_SOR_SEQ_INST(4));
556 DUMP_REG(NV_SOR_SEQ_INST(5));
557 DUMP_REG(NV_SOR_SEQ_INST(6));
558 DUMP_REG(NV_SOR_SEQ_INST(7));
559 DUMP_REG(NV_SOR_SEQ_INST(8));
560 DUMP_REG(NV_SOR_PWM_DIV);
561 DUMP_REG(NV_SOR_PWM_CTL);
562 DUMP_REG(NV_SOR_MSCHECK);
563 DUMP_REG(NV_SOR_XBAR_CTRL);
564 DUMP_REG(NV_SOR_DP_LINKCTL(0));
565 DUMP_REG(NV_SOR_DP_LINKCTL(1));
566 DUMP_REG(NV_SOR_DC(0));
567 DUMP_REG(NV_SOR_DC(1));
568 DUMP_REG(NV_SOR_LANE_DRIVE_CURRENT(0));
569 DUMP_REG(NV_SOR_PR(0));
570 DUMP_REG(NV_SOR_LANE4_PREEMPHASIS(0));
571 DUMP_REG(NV_SOR_POSTCURSOR(0));
572 DUMP_REG(NV_SOR_DP_CONFIG(0));
573 DUMP_REG(NV_SOR_DP_CONFIG(1));
574 DUMP_REG(NV_SOR_DP_MN(0));
575 DUMP_REG(NV_SOR_DP_MN(1));
576 DUMP_REG(NV_SOR_DP_PADCTL(0));
577 DUMP_REG(NV_SOR_DP_PADCTL(1));
578 DUMP_REG(NV_SOR_DP_DEBUG(0));
579 DUMP_REG(NV_SOR_DP_DEBUG(1));
580 DUMP_REG(NV_SOR_DP_SPARE(0));
581 DUMP_REG(NV_SOR_DP_SPARE(1));
582 DUMP_REG(NV_SOR_DP_TPG);
583
584 return;
585}
586#endif
587
588static void tegra_dc_sor_config_panel(struct tegra_dc_sor_data *sor,
589 int is_lvds)
590{
591 const struct tegra_dc *dc = sor->dc;
592 const struct tegra_dc_dp_data *dp = dc->out;
593 const struct tegra_dc_dp_link_config *link_cfg = &dp->link_cfg;
594 const struct soc_nvidia_tegra210_config *config = dc->config;
595
596 const int head_num = 0;
597 u32 reg_val = NV_SOR_STATE1_ASY_OWNER_HEAD0 << head_num;
598 u32 vsync_end, hsync_end;
599 u32 vblank_end, hblank_end;
600 u32 vblank_start, hblank_start;
601
602 reg_val |= is_lvds ? NV_SOR_STATE1_ASY_PROTOCOL_LVDS_CUSTOM :
603 NV_SOR_STATE1_ASY_PROTOCOL_DP_A;
604 reg_val |= NV_SOR_STATE1_ASY_SUBOWNER_NONE |
605 NV_SOR_STATE1_ASY_CRCMODE_COMPLETE_RASTER;
606
607 reg_val |= NV_SOR_STATE1_ASY_HSYNCPOL_NEGATIVE_TRUE;
608 reg_val |= NV_SOR_STATE1_ASY_VSYNCPOL_NEGATIVE_TRUE;
609 reg_val |= (link_cfg->bits_per_pixel > 18) ?
610 NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_24_444 :
611 NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_18_444;
612
613 tegra_sor_writel(sor, NV_SOR_STATE1, reg_val);
614
615 /* Skipping programming NV_HEAD_STATE0, assuming:
616 interlacing: PROGRESSIVE, dynamic range: VESA, colorspace: RGB */
617
618 tegra_sor_writel(sor, NV_HEAD_STATE1(head_num),
619 vtotal(config) << NV_HEAD_STATE1_VTOTAL_SHIFT |
620 htotal(config) << NV_HEAD_STATE1_HTOTAL_SHIFT);
621
622 vsync_end = config->vsync_width - 1;
623 hsync_end = config->hsync_width - 1;
624 tegra_sor_writel(sor, NV_HEAD_STATE2(head_num),
625 vsync_end << NV_HEAD_STATE2_VSYNC_END_SHIFT |
626 hsync_end << NV_HEAD_STATE2_HSYNC_END_SHIFT);
627
628 vblank_end = vsync_end + config->vback_porch;
629 hblank_end = hsync_end + config->hback_porch;
630 tegra_sor_writel(sor, NV_HEAD_STATE3(head_num),
631 vblank_end << NV_HEAD_STATE3_VBLANK_END_SHIFT |
632 hblank_end << NV_HEAD_STATE3_HBLANK_END_SHIFT);
633
634 vblank_start = vblank_end + config->yres;
635 hblank_start = hblank_end + config->xres;
636 tegra_sor_writel(sor, NV_HEAD_STATE4(head_num),
637 vblank_start << NV_HEAD_STATE4_VBLANK_START_SHIFT |
638 hblank_start << NV_HEAD_STATE4_HBLANK_START_SHIFT);
639
640 /* TODO: adding interlace mode support */
641 tegra_sor_writel(sor, NV_HEAD_STATE5(head_num), 0x1);
642
643 tegra_sor_write_field(sor, NV_SOR_CSTM,
644 NV_SOR_CSTM_ROTCLK_DEFAULT_MASK |
645 NV_SOR_CSTM_LVDS_EN_ENABLE,
646 2 << NV_SOR_CSTM_ROTCLK_SHIFT |
647 is_lvds ? NV_SOR_CSTM_LVDS_EN_ENABLE :
648 NV_SOR_CSTM_LVDS_EN_DISABLE);
649
650 tegra_dc_sor_config_pwm(sor, 1024, 1024);
651}
652
653static void tegra_dc_sor_enable_dc(struct tegra_dc_sor_data *sor)
654{
655 struct tegra_dc *dc = sor->dc;
656 struct display_controller *disp_ctrl = (void *)dc->base;
657
658 u32 reg_val = READL(&disp_ctrl->cmd.state_access);
659
660 WRITEL(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access);
661 WRITEL(VSYNC_H_POSITION(1), &disp_ctrl->disp.disp_timing_opt);
662
663 /* Enable DC now - otherwise pure text console may not show. */
664 WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd);
665 WRITEL(reg_val, &disp_ctrl->cmd.state_access);
666}
667
668void tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor)
669{
670 const struct tegra_dc_dp_link_config *link_cfg = sor->link_cfg;
671
672 tegra_sor_write_field(sor, NV_SOR_CLK_CNTRL,
673 NV_SOR_CLK_CNTRL_DP_CLK_SEL_MASK,
674 NV_SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK);
675
676 tegra_sor_write_field(sor, NV_SOR_PLL2,
677 NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK,
678 NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE);
679 udelay(25);
680
681 tegra_sor_write_field(sor, NV_SOR_PLL3,
682 NV_SOR_PLL3_PLLVDD_MODE_MASK,
683 NV_SOR_PLL3_PLLVDD_MODE_V3_3);
684 tegra_sor_writel(sor, NV_SOR_PLL0,
685 0xf << NV_SOR_PLL0_ICHPMP_SHFIT |
686 0x3 << NV_SOR_PLL0_VCOCAP_SHIFT |
687 NV_SOR_PLL0_PLLREG_LEVEL_V45 |
688 NV_SOR_PLL0_RESISTORSEL_EXT |
689 NV_SOR_PLL0_PWR_ON | NV_SOR_PLL0_VCOPD_RESCIND);
690 tegra_sor_write_field(sor, NV_SOR_PLL2,
691 NV_SOR_PLL2_AUX1_SEQ_MASK | NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE |
692 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
693 NV_SOR_PLL2_AUX1_SEQ_PLLCAPPD_OVERRIDE |
694 NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE |
695 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE);
696 tegra_sor_writel(sor, NV_SOR_PLL1,
697 NV_SOR_PLL1_TERM_COMPOUT_HIGH | NV_SOR_PLL1_TMDS_TERM_ENABLE);
698
699 if (tegra_dc_sor_poll_register(sor, NV_SOR_PLL2,
700 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
701 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE,
702 100, TEGRA_SOR_TIMEOUT_MS * 1000)) {
703 printk(BIOS_ERR, "DP failed to lock PLL\n");
704 return;
705 }
706
707 tegra_sor_write_field(sor, NV_SOR_PLL2,
708 NV_SOR_PLL2_AUX2_MASK | NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK,
709 NV_SOR_PLL2_AUX2_OVERRIDE_POWERDOWN |
710 NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE);
711
712 tegra_dc_sor_power_up(sor, 0);
713
714 /* re-enable SOR clock */
715 tegra_sor_enable_edp_clock(sor); /* select pll_dp as clock source */
716
717 /* Power up lanes */
718 tegra_dc_sor_power_dplanes(sor, link_cfg->lane_count, 1);
719
720 tegra_dc_sor_set_dp_mode(sor, link_cfg);
721
722}
723
724void tegra_dc_sor_attach(struct tegra_dc_sor_data *sor)
725{
726 u32 reg_val;
727 struct display_controller *disp_ctrl = (void *)sor->dc->base;
728
729 tegra_dc_sor_enable_dc(sor);
730 tegra_dc_sor_config_panel(sor, 0);
731
732 WRITEL(0x9f00, &disp_ctrl->cmd.state_ctrl);
733 WRITEL(0x9f, &disp_ctrl->cmd.state_ctrl);
734
735 WRITEL(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE |
736 PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
737 &disp_ctrl->cmd.disp_pow_ctrl);
738
739 reg_val = tegra_sor_readl(sor, NV_SOR_TEST);
740 if (reg_val & NV_SOR_TEST_ATTACHED_TRUE)
741 return;
742
743 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
744 NV_SOR_SUPER_STATE1_ATTACHED_NO);
745
746 /*
747 * Enable display2sor clock at least 2 cycles before DC start,
748 * to clear sor internal valid signal.
749 */
750
751 /* Stop dc for 3 cycles */
752 WRITEL(0, &disp_ctrl->disp.disp_win_opt);
753 WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
754 udelay(FRAME_IN_MS * 1000 * 3);
755
756 /* Attach head */
757 tegra_dc_sor_update(sor);
758 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
759 NV_SOR_SUPER_STATE1_ATTACHED_YES);
760 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
761 NV_SOR_SUPER_STATE1_ATTACHED_YES |
762 NV_SOR_SUPER_STATE1_ASY_HEAD_OP_AWAKE |
763 NV_SOR_SUPER_STATE1_ASY_ORMODE_NORMAL);
764 tegra_dc_sor_super_update(sor);
765
766 /* wait for another 5 cycles */
767 udelay(FRAME_IN_MS * 1000 * 5);
768
769 /* Re-enable dc */
770 WRITEL(READ_MUX_ACTIVE | WRITE_MUX_ACTIVE,
771 &disp_ctrl->cmd.state_access);
772 WRITEL(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt);
773
774 WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd);
775 WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
776
777 if (tegra_dc_sor_poll_register(sor, NV_SOR_TEST,
778 NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK,
779 NV_SOR_TEST_ACT_HEAD_OPMODE_AWAKE,
780 100, TEGRA_SOR_ATTACH_TIMEOUT_MS * 1000))
781 printk(BIOS_ERR, "dc timeout waiting for OPMOD = AWAKE\n");
782 else
783 printk(BIOS_INFO, "%s: sor is attached\n", __func__);
784
785#if DEBUG_SOR
786 dump_sor_reg(sor);
787#endif
788}
789
790void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
791 const struct tegra_dc_dp_link_config *link_cfg)
792{
793 tegra_sor_writel(sor, NV_SOR_LANE_DRIVE_CURRENT(sor->portnum),
794 link_cfg->drive_current);
795 tegra_sor_writel(sor, NV_SOR_PR(sor->portnum),
796 link_cfg->preemphasis);
797 tegra_sor_writel(sor, NV_SOR_POSTCURSOR(sor->portnum),
798 link_cfg->postcursor);
799 tegra_sor_writel(sor, NV_SOR_LVDS, 0);
800
801 tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw);
802 tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count);
803
804 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
805 NV_SOR_DP_PADCTL_TX_PU_ENABLE |
806 NV_SOR_DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK,
807 NV_SOR_DP_PADCTL_TX_PU_ENABLE |
808 2 << NV_SOR_DP_PADCTL_TX_PU_VALUE_SHIFT);
809
810 /* Precharge */
811 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
812 0xf0, 0xf0);
813 udelay(20);
814
815 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
816 0xf0, 0x0);
817}
818
819void tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor)
820{
821 u32 drive_current = 0;
822 u32 pre_emphasis = 0;
823
824 /* Set to a known-good pre-calibrated setting */
825 switch (sor->link_cfg->link_bw) {
826 case SOR_LINK_SPEED_G1_62:
827 case SOR_LINK_SPEED_G2_7:
828 drive_current = 0x13131313;
829 pre_emphasis = 0;
830 break;
831 case SOR_LINK_SPEED_G5_4:
832 printk(BIOS_WARNING, "T1xx does not support 5.4G link"
833 " clock.\n");
834 default:
835 printk(BIOS_WARNING, "Invalid sor link bandwidth: %d\n",
836 sor->link_cfg->link_bw);
837 return;
838 }
839
840 tegra_sor_writel(sor, NV_SOR_LANE_DRIVE_CURRENT(sor->portnum),
841 drive_current);
842 tegra_sor_writel(sor, NV_SOR_PR(sor->portnum), pre_emphasis);
843}
844
845void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor)
846{
847 u32 pad_ctrl = 0;
848 int err = 0;
849
850 switch (sor->link_cfg->lane_count) {
851 case 4:
852 pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO |
853 NV_SOR_DP_PADCTL_PD_TXD_1_NO |
854 NV_SOR_DP_PADCTL_PD_TXD_2_NO |
855 NV_SOR_DP_PADCTL_PD_TXD_3_NO);
856 break;
857 case 2:
858 pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO |
859 NV_SOR_DP_PADCTL_PD_TXD_1_NO |
860 NV_SOR_DP_PADCTL_PD_TXD_2_YES |
861 NV_SOR_DP_PADCTL_PD_TXD_3_YES);
862 break;
863 case 1:
864 pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO |
865 NV_SOR_DP_PADCTL_PD_TXD_1_YES |
866 NV_SOR_DP_PADCTL_PD_TXD_2_YES |
867 NV_SOR_DP_PADCTL_PD_TXD_3_YES);
868 break;
869 default:
870 printk(BIOS_ERR, "Invalid sor lane count: %u\n",
871 sor->link_cfg->lane_count);
872 return;
873 }
874
875 pad_ctrl |= NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN;
876 tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), pad_ctrl);
877
878 err = tegra_dc_sor_enable_lane_sequencer(sor, 0, 0);
879 if (err) {
880 printk(BIOS_ERR,
881 "Wait for lane power down failed: %d\n", err);
882 return;
883 }
884}
885
886void tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor)
887{
888 const struct tegra_dc_dp_link_config *cfg = sor->link_cfg;
889 u32 val = 0;
890
891 switch (cfg->lane_count) {
892 case 4:
893 val |= (NV_SOR_DP_PADCTL_PD_TXD_3_NO |
894 NV_SOR_DP_PADCTL_PD_TXD_2_NO);
895 /* fall through */
896 case 2:
897 val |= NV_SOR_DP_PADCTL_PD_TXD_1_NO;
898 /* fall through */
899 case 1:
900 val |= NV_SOR_DP_PADCTL_PD_TXD_0_NO;
901 break;
902 default:
903 printk(BIOS_ERR,
904 "dp: invalid lane number %d\n", cfg->lane_count);
905 return;
906 }
907
908 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
909 (0xf << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT),
910 (val << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT));
911 udelay(100);
912 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
913 (0xf << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT), 0);
914}
915
916static u32 tegra_dc_poll_register(void *reg,
917 u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_us)
918{
919 u32 temp = timeout_us;
920 u32 reg_val = 0;
921
922 do {
923 udelay(poll_interval_us);
924 reg_val = READL(reg);
925 if (timeout_us > poll_interval_us)
926 timeout_us -= poll_interval_us;
927 else
928 break;
929 } while ((reg_val & mask) != exp_val);
930
931 if ((reg_val & mask) == exp_val)
932 return 0; /* success */
933
934 return temp;
935}
936
937static void tegra_dc_sor_general_act(struct display_controller *disp_ctrl)
938{
939 WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
940
941 if (tegra_dc_poll_register(&disp_ctrl->cmd.state_ctrl,
942 GENERAL_ACT_REQ, 0, 100,
943 TEGRA_DC_POLL_TIMEOUT_MS*1000))
944 printk(BIOS_ERR,
945 "dc timeout waiting for DC to stop\n");
946}
947
948static struct tegra_dc_mode min_mode = {
949 .h_ref_to_sync = 0,
950 .v_ref_to_sync = 1,
951 .h_sync_width = 1,
952 .v_sync_width = 1,
953 .h_back_porch = 20,
954 .v_back_porch = 0,
955 .h_active = 16,
956 .v_active = 16,
957 .h_front_porch = 1,
958 .v_front_porch = 2,
959};
960
961/* Disable windows and set minimum raster timings */
962static void
963tegra_dc_sor_disable_win_short_raster(struct display_controller *disp_ctrl,
964 int *dc_reg_ctx)
965{
966 int selected_windows, i;
967
968 selected_windows = READL(&disp_ctrl->cmd.disp_win_header);
969
970 /* Store and clear window options */
971 for (i = 0; i < DC_N_WINDOWS; ++i) {
972 WRITEL(WINDOW_A_SELECT << i, &disp_ctrl->cmd.disp_win_header);
973 dc_reg_ctx[i] = READL(&disp_ctrl->win.win_opt);
974 WRITEL(0, &disp_ctrl->win.win_opt);
975 WRITEL(WIN_A_ACT_REQ << i, &disp_ctrl->cmd.state_ctrl);
976 }
977
978 WRITEL(selected_windows, &disp_ctrl->cmd.disp_win_header);
979
980 /* Store current raster timings and set minimum timings */
981 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.ref_to_sync);
982 WRITEL(min_mode.h_ref_to_sync | (min_mode.v_ref_to_sync << 16),
983 &disp_ctrl->disp.ref_to_sync);
984
985 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.sync_width);
986 WRITEL(min_mode.h_sync_width | (min_mode.v_sync_width << 16),
987 &disp_ctrl->disp.sync_width);
988
989 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.back_porch);
990 WRITEL(min_mode.h_back_porch |
991 min_mode.v_back_porch << 16,
992 &disp_ctrl->disp.back_porch);
993
994 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.front_porch);
995 WRITEL(min_mode.h_front_porch |
996 min_mode.v_front_porch << 16,
997 &disp_ctrl->disp.front_porch);
998
999 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.disp_active);
1000 WRITEL(min_mode.h_active | (min_mode.v_active << 16),
1001 &disp_ctrl->disp.disp_active);
1002
1003 WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
1004}
1005
1006/* Restore previous windows status and raster timings */
1007static void
1008tegra_dc_sor_restore_win_and_raster(struct display_controller *disp_ctrl,
1009 int *dc_reg_ctx)
1010{
1011 int selected_windows, i;
1012
1013 selected_windows = READL(&disp_ctrl->cmd.disp_win_header);
1014
1015 for (i = 0; i < DC_N_WINDOWS; ++i) {
1016 WRITEL(WINDOW_A_SELECT << i, &disp_ctrl->cmd.disp_win_header);
1017 WRITEL(dc_reg_ctx[i], &disp_ctrl->win.win_opt);
1018 WRITEL(WIN_A_ACT_REQ << i, &disp_ctrl->cmd.state_ctrl);
1019 }
1020
1021 WRITEL(selected_windows, &disp_ctrl->cmd.disp_win_header);
1022
1023 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.ref_to_sync);
1024 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.sync_width);
1025 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.back_porch);
1026 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.front_porch);
1027 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.disp_active);
1028
1029 WRITEL(GENERAL_UPDATE, &disp_ctrl->cmd.state_ctrl);
1030}
1031
1032static void tegra_dc_sor_enable_sor(struct tegra_dc_sor_data *sor, int enable)
1033{
1034 struct display_controller *disp_ctrl = (void *)sor->dc->base;
1035 u32 reg_val = READL(&disp_ctrl->disp.disp_win_opt);
1036
1037 reg_val = enable ? reg_val | SOR_ENABLE : reg_val & ~SOR_ENABLE;
1038 WRITEL(reg_val, &disp_ctrl->disp.disp_win_opt);
1039}
1040
1041void tegra_dc_detach(struct tegra_dc_sor_data *sor)
1042{
1043 struct display_controller *disp_ctrl = (void *)sor->dc->base;
1044 int dc_reg_ctx[DC_N_WINDOWS + 5];
1045 unsigned long dc_int_mask;
1046
1047 /* Sleep mode */
1048 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
1049 NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SLEEP |
1050 NV_SOR_SUPER_STATE1_ASY_ORMODE_SAFE |
1051 NV_SOR_SUPER_STATE1_ATTACHED_YES);
1052 tegra_dc_sor_super_update(sor);
1053
1054 tegra_dc_sor_disable_win_short_raster(disp_ctrl, dc_reg_ctx);
1055
1056 if (tegra_dc_sor_poll_register(sor, NV_SOR_TEST,
1057 NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK,
1058 NV_SOR_TEST_ACT_HEAD_OPMODE_SLEEP,
1059 100, TEGRA_SOR_ATTACH_TIMEOUT_MS*1000)) {
1060 printk(BIOS_ERR,
1061 "dc timeout waiting for OPMOD = SLEEP\n");
1062 }
1063
1064 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
1065 NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SLEEP |
1066 NV_SOR_SUPER_STATE1_ASY_ORMODE_SAFE |
1067 NV_SOR_SUPER_STATE1_ATTACHED_NO);
1068
1069 /* Mask DC interrupts during the 2 dummy frames required for detach */
1070 dc_int_mask = READL(&disp_ctrl->cmd.int_mask);
1071 WRITEL(0, &disp_ctrl->cmd.int_mask);
1072
1073 /* Stop DC->SOR path */
1074 tegra_dc_sor_enable_sor(sor, 0);
1075 tegra_dc_sor_general_act(disp_ctrl);
1076
1077 /* Stop DC */
1078 WRITEL(DISP_CTRL_MODE_STOP, &disp_ctrl->cmd.disp_cmd);
1079 tegra_dc_sor_general_act(disp_ctrl);
1080
1081 tegra_dc_sor_restore_win_and_raster(disp_ctrl, dc_reg_ctx);
1082
1083 WRITEL(dc_int_mask, &disp_ctrl->cmd.int_mask);
1084}