blob: 9d6f94d2e94f121b595ee1ab8bbd4553b04e6d4b [file] [log] [blame]
Angel Ponsa2ee7612020-04-04 18:51:15 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Angel Ponsa2ee7612020-04-04 18:51:15 +02002
Patrick Georgi40a3e322015-06-22 19:41:29 +02003/*
4 * drivers/video/tegra/dc/sor.c
Patrick Georgi40a3e322015-06-22 19:41:29 +02005 */
6
7#include <console/console.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +02008#include <stdint.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +02009#include <delay.h>
10#include <soc/addressmap.h>
11#include <device/device.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +020012#include <boot/tables.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +020013#include <soc/nvidia/tegra/dc.h>
14#include <soc/nvidia/tegra/types.h>
15#include <soc/sor.h>
16#include <soc/nvidia/tegra/displayport.h>
17#include <soc/clk_rst.h>
18#include <soc/clock.h>
19#include "chip.h"
20#include <soc/display.h>
21
22#define DEBUG_SOR 0
23
24#define APBDEV_PMC_DPD_SAMPLE (0x20)
25#define APBDEV_PMC_DPD_SAMPLE_ON_DISABLE (0)
26#define APBDEV_PMC_DPD_SAMPLE_ON_ENABLE (1)
27#define APBDEV_PMC_SEL_DPD_TIM (0x1c8)
28#define APBDEV_PMC_SEL_DPD_TIM_SEL_DPD_TIM_DEFAULT (0x7f)
29#define APBDEV_PMC_IO_DPD2_REQ (0x1c0)
30#define APBDEV_PMC_IO_DPD2_REQ_LVDS_SHIFT (25)
31#define APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF (0 << 25)
32#define APBDEV_PMC_IO_DPD2_REQ_LVDS_ON (1 << 25)
33#define APBDEV_PMC_IO_DPD2_REQ_CODE_SHIFT (30)
34#define APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK (0x3 << 30)
35#define APBDEV_PMC_IO_DPD2_REQ_CODE_IDLE (0 << 30)
36#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF (1 << 30)
37#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON (2 << 30)
38#define APBDEV_PMC_IO_DPD2_STATUS (0x1c4)
39#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_SHIFT (25)
40#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_OFF (0 << 25)
41#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON (1 << 25)
42
43#define DC_N_WINDOWS 5
44
45static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg)
46{
Elyes Haouas41865cc2022-11-18 15:09:28 +010047 void *addr = sor->base + (u32)(reg << 2);
Patrick Georgi40a3e322015-06-22 19:41:29 +020048 u32 reg_val = READL(addr);
49 return reg_val;
50}
51
52static inline void tegra_sor_writel(struct tegra_dc_sor_data *sor,
53 u32 reg, u32 val)
54{
Elyes Haouas41865cc2022-11-18 15:09:28 +010055 void *addr = sor->base + (u32)(reg << 2);
Patrick Georgi40a3e322015-06-22 19:41:29 +020056 WRITEL(val, addr);
57}
58
59static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor,
60 u32 reg, u32 mask, u32 val)
61{
62 u32 reg_val = tegra_sor_readl(sor, reg);
63 reg_val &= ~mask;
64 reg_val |= val;
65 tegra_sor_writel(sor, reg, reg_val);
66}
67
68void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor)
69{
70 tegra_sor_write_field(sor,
71 NV_SOR_DP_PADCTL(sor->portnum),
72 NV_SOR_DP_PADCTL_TX_PU_MASK,
73 NV_SOR_DP_PADCTL_TX_PU_DISABLE);
74}
75
76void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask,
77 u32 pe_reg, u32 vs_reg, u32 pc_reg, u8 pc_supported)
78{
79 tegra_sor_write_field(sor, NV_SOR_PR(sor->portnum),
80 mask, pe_reg);
81 tegra_sor_write_field(sor, NV_SOR_DC(sor->portnum),
82 mask, vs_reg);
83 if (pc_supported) {
84 tegra_sor_write_field(
85 sor, NV_SOR_POSTCURSOR(sor->portnum),
86 mask, pc_reg);
87 }
88}
89
90static u32 tegra_dc_sor_poll_register(struct tegra_dc_sor_data *sor,
91 u32 reg, u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_us)
92{
93 u32 temp = timeout_us;
94 u32 reg_val = 0;
95
96 do {
97 udelay(poll_interval_us);
98 reg_val = tegra_sor_readl(sor, reg);
99 if (timeout_us > poll_interval_us)
100 timeout_us -= poll_interval_us;
101 else
102 break;
103 } while ((reg_val & mask) != exp_val);
104
105 if ((reg_val & mask) == exp_val)
106 return 0; /* success */
107 printk(BIOS_ERR,
108 "sor_poll_register 0x%x: timeout, "
109 "(reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n",
110 reg, reg_val, mask, exp_val);
111
112 return temp;
113}
114
115int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd)
116{
117 u32 reg_val;
118 u32 orig_val;
119
120 orig_val = tegra_sor_readl(sor, NV_SOR_PWR);
121
122 reg_val = pu_pd ? NV_SOR_PWR_NORMAL_STATE_PU :
123 NV_SOR_PWR_NORMAL_STATE_PD; /* normal state only */
124
125 if (reg_val == orig_val)
126 return 0; /* No update needed */
127
128 reg_val |= NV_SOR_PWR_SETTING_NEW_TRIGGER;
129 tegra_sor_writel(sor, NV_SOR_PWR, reg_val);
130
131 /* Poll to confirm it is done */
132 if (tegra_dc_sor_poll_register(sor, NV_SOR_PWR,
133 NV_SOR_PWR_SETTING_NEW_DEFAULT_MASK,
134 NV_SOR_PWR_SETTING_NEW_DONE,
135 100, TEGRA_SOR_TIMEOUT_MS * 1000)) {
136 printk(BIOS_ERR,
137 "dc timeout waiting for SOR_PWR = NEW_DONE\n");
138 return -EFAULT;
139 }
140 return 0;
141}
142
143void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena,
144 u8 training_pattern, const struct tegra_dc_dp_link_config *link_cfg)
145{
146 u32 reg_val;
147
148 reg_val = tegra_sor_readl(sor, NV_SOR_DP_LINKCTL(sor->portnum));
149
150 if (ena)
151 reg_val |= NV_SOR_DP_LINKCTL_ENABLE_YES;
152 else
153 reg_val &= NV_SOR_DP_LINKCTL_ENABLE_NO;
154
155 reg_val &= ~NV_SOR_DP_LINKCTL_TUSIZE_MASK;
156 reg_val |= (link_cfg->tu_size << NV_SOR_DP_LINKCTL_TUSIZE_SHIFT);
157
158 if (link_cfg->enhanced_framing)
159 reg_val |= NV_SOR_DP_LINKCTL_ENHANCEDFRAME_ENABLE;
160
161 tegra_sor_writel(sor, NV_SOR_DP_LINKCTL(sor->portnum), reg_val);
162
163 switch (training_pattern) {
164 case training_pattern_1:
165 tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x41414141);
166 break;
167 case training_pattern_2:
168 case training_pattern_3:
169 reg_val = (link_cfg->link_bw == SOR_LINK_SPEED_G5_4) ?
170 0x43434343 : 0x42424242;
171 tegra_sor_writel(sor, NV_SOR_DP_TPG, reg_val);
172 break;
173 default:
174 tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x50505050);
175 break;
176 }
177}
178
179static int tegra_dc_sor_enable_lane_sequencer(struct tegra_dc_sor_data *sor,
180 int pu, int is_lvds)
181{
182 u32 reg_val;
183
184 /* SOR lane sequencer */
185 if (pu)
186 reg_val = NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER |
187 NV_SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
188 NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PU;
189 else
190 reg_val = NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER |
191 NV_SOR_LANE_SEQ_CTL_SEQUENCE_UP |
192 NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PD;
193
194 if (is_lvds)
195 reg_val |= 15 << NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT;
196 else
197 reg_val |= 1 << NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT;
198
199 tegra_sor_writel(sor, NV_SOR_LANE_SEQ_CTL, reg_val);
200
201 if (tegra_dc_sor_poll_register(sor, NV_SOR_LANE_SEQ_CTL,
202 NV_SOR_LANE_SEQ_CTL_SETTING_MASK,
203 NV_SOR_LANE_SEQ_CTL_SETTING_NEW_DONE,
204 100, TEGRA_SOR_TIMEOUT_MS*1000)) {
205 printk(BIOS_ERR,
206 "dp: timeout while waiting for SOR lane sequencer "
207 "to power down langes\n");
208 return -1;
209 }
210 return 0;
211}
212
213static int tegra_dc_sor_power_dplanes(struct tegra_dc_sor_data *sor,
214 u32 lane_count, int pu)
215{
216 u32 reg_val;
217
218 reg_val = tegra_sor_readl(sor, NV_SOR_DP_PADCTL(sor->portnum));
219
220 if (pu) {
221 switch (lane_count) {
222 case 4:
223 reg_val |= (NV_SOR_DP_PADCTL_PD_TXD_3_NO |
224 NV_SOR_DP_PADCTL_PD_TXD_2_NO);
Arthur Heymansfff20212021-03-15 14:56:16 +0100225 fallthrough;
Patrick Georgi40a3e322015-06-22 19:41:29 +0200226 case 2:
227 reg_val |= NV_SOR_DP_PADCTL_PD_TXD_1_NO;
Arthur Heymansfff20212021-03-15 14:56:16 +0100228 fallthrough;
Patrick Georgi40a3e322015-06-22 19:41:29 +0200229 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", \
Elyes Haouasfb0a7512022-09-29 12:29:17 +0200518 #a, a, tegra_sor_readl(sor, a))
Patrick Georgi40a3e322015-06-22 19:41:29 +0200519
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);
Patrick Georgi40a3e322015-06-22 19:41:29 +0200583}
584#endif
585
586static void tegra_dc_sor_config_panel(struct tegra_dc_sor_data *sor,
587 int is_lvds)
588{
589 const struct tegra_dc *dc = sor->dc;
590 const struct tegra_dc_dp_data *dp = dc->out;
591 const struct tegra_dc_dp_link_config *link_cfg = &dp->link_cfg;
592 const struct soc_nvidia_tegra210_config *config = dc->config;
593
594 const int head_num = 0;
595 u32 reg_val = NV_SOR_STATE1_ASY_OWNER_HEAD0 << head_num;
596 u32 vsync_end, hsync_end;
597 u32 vblank_end, hblank_end;
598 u32 vblank_start, hblank_start;
599
600 reg_val |= is_lvds ? NV_SOR_STATE1_ASY_PROTOCOL_LVDS_CUSTOM :
601 NV_SOR_STATE1_ASY_PROTOCOL_DP_A;
602 reg_val |= NV_SOR_STATE1_ASY_SUBOWNER_NONE |
603 NV_SOR_STATE1_ASY_CRCMODE_COMPLETE_RASTER;
604
605 reg_val |= NV_SOR_STATE1_ASY_HSYNCPOL_NEGATIVE_TRUE;
606 reg_val |= NV_SOR_STATE1_ASY_VSYNCPOL_NEGATIVE_TRUE;
607 reg_val |= (link_cfg->bits_per_pixel > 18) ?
608 NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_24_444 :
609 NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_18_444;
610
611 tegra_sor_writel(sor, NV_SOR_STATE1, reg_val);
612
613 /* Skipping programming NV_HEAD_STATE0, assuming:
614 interlacing: PROGRESSIVE, dynamic range: VESA, colorspace: RGB */
615
616 tegra_sor_writel(sor, NV_HEAD_STATE1(head_num),
617 vtotal(config) << NV_HEAD_STATE1_VTOTAL_SHIFT |
618 htotal(config) << NV_HEAD_STATE1_HTOTAL_SHIFT);
619
620 vsync_end = config->vsync_width - 1;
621 hsync_end = config->hsync_width - 1;
622 tegra_sor_writel(sor, NV_HEAD_STATE2(head_num),
623 vsync_end << NV_HEAD_STATE2_VSYNC_END_SHIFT |
624 hsync_end << NV_HEAD_STATE2_HSYNC_END_SHIFT);
625
626 vblank_end = vsync_end + config->vback_porch;
627 hblank_end = hsync_end + config->hback_porch;
628 tegra_sor_writel(sor, NV_HEAD_STATE3(head_num),
629 vblank_end << NV_HEAD_STATE3_VBLANK_END_SHIFT |
630 hblank_end << NV_HEAD_STATE3_HBLANK_END_SHIFT);
631
632 vblank_start = vblank_end + config->yres;
633 hblank_start = hblank_end + config->xres;
634 tegra_sor_writel(sor, NV_HEAD_STATE4(head_num),
635 vblank_start << NV_HEAD_STATE4_VBLANK_START_SHIFT |
636 hblank_start << NV_HEAD_STATE4_HBLANK_START_SHIFT);
637
638 /* TODO: adding interlace mode support */
639 tegra_sor_writel(sor, NV_HEAD_STATE5(head_num), 0x1);
640
641 tegra_sor_write_field(sor, NV_SOR_CSTM,
642 NV_SOR_CSTM_ROTCLK_DEFAULT_MASK |
643 NV_SOR_CSTM_LVDS_EN_ENABLE,
644 2 << NV_SOR_CSTM_ROTCLK_SHIFT |
645 is_lvds ? NV_SOR_CSTM_LVDS_EN_ENABLE :
646 NV_SOR_CSTM_LVDS_EN_DISABLE);
647
648 tegra_dc_sor_config_pwm(sor, 1024, 1024);
649}
650
651static void tegra_dc_sor_enable_dc(struct tegra_dc_sor_data *sor)
652{
653 struct tegra_dc *dc = sor->dc;
654 struct display_controller *disp_ctrl = (void *)dc->base;
655
656 u32 reg_val = READL(&disp_ctrl->cmd.state_access);
657
658 WRITEL(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access);
659 WRITEL(VSYNC_H_POSITION(1), &disp_ctrl->disp.disp_timing_opt);
660
661 /* Enable DC now - otherwise pure text console may not show. */
662 WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd);
663 WRITEL(reg_val, &disp_ctrl->cmd.state_access);
664}
665
666void tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor)
667{
668 const struct tegra_dc_dp_link_config *link_cfg = sor->link_cfg;
669
670 tegra_sor_write_field(sor, NV_SOR_CLK_CNTRL,
671 NV_SOR_CLK_CNTRL_DP_CLK_SEL_MASK,
672 NV_SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK);
673
674 tegra_sor_write_field(sor, NV_SOR_PLL2,
675 NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK,
676 NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE);
677 udelay(25);
678
679 tegra_sor_write_field(sor, NV_SOR_PLL3,
680 NV_SOR_PLL3_PLLVDD_MODE_MASK,
681 NV_SOR_PLL3_PLLVDD_MODE_V3_3);
682 tegra_sor_writel(sor, NV_SOR_PLL0,
683 0xf << NV_SOR_PLL0_ICHPMP_SHFIT |
684 0x3 << NV_SOR_PLL0_VCOCAP_SHIFT |
685 NV_SOR_PLL0_PLLREG_LEVEL_V45 |
686 NV_SOR_PLL0_RESISTORSEL_EXT |
687 NV_SOR_PLL0_PWR_ON | NV_SOR_PLL0_VCOPD_RESCIND);
688 tegra_sor_write_field(sor, NV_SOR_PLL2,
689 NV_SOR_PLL2_AUX1_SEQ_MASK | NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE |
690 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
691 NV_SOR_PLL2_AUX1_SEQ_PLLCAPPD_OVERRIDE |
692 NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE |
693 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE);
694 tegra_sor_writel(sor, NV_SOR_PLL1,
695 NV_SOR_PLL1_TERM_COMPOUT_HIGH | NV_SOR_PLL1_TMDS_TERM_ENABLE);
696
697 if (tegra_dc_sor_poll_register(sor, NV_SOR_PLL2,
698 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
699 NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE,
700 100, TEGRA_SOR_TIMEOUT_MS * 1000)) {
701 printk(BIOS_ERR, "DP failed to lock PLL\n");
702 return;
703 }
704
705 tegra_sor_write_field(sor, NV_SOR_PLL2,
706 NV_SOR_PLL2_AUX2_MASK | NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK,
707 NV_SOR_PLL2_AUX2_OVERRIDE_POWERDOWN |
708 NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE);
709
710 tegra_dc_sor_power_up(sor, 0);
711
712 /* re-enable SOR clock */
713 tegra_sor_enable_edp_clock(sor); /* select pll_dp as clock source */
714
715 /* Power up lanes */
716 tegra_dc_sor_power_dplanes(sor, link_cfg->lane_count, 1);
717
718 tegra_dc_sor_set_dp_mode(sor, link_cfg);
Patrick Georgi40a3e322015-06-22 19:41:29 +0200719}
720
721void tegra_dc_sor_attach(struct tegra_dc_sor_data *sor)
722{
723 u32 reg_val;
724 struct display_controller *disp_ctrl = (void *)sor->dc->base;
725
726 tegra_dc_sor_enable_dc(sor);
727 tegra_dc_sor_config_panel(sor, 0);
728
729 WRITEL(0x9f00, &disp_ctrl->cmd.state_ctrl);
730 WRITEL(0x9f, &disp_ctrl->cmd.state_ctrl);
731
732 WRITEL(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE |
733 PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
734 &disp_ctrl->cmd.disp_pow_ctrl);
735
736 reg_val = tegra_sor_readl(sor, NV_SOR_TEST);
737 if (reg_val & NV_SOR_TEST_ATTACHED_TRUE)
738 return;
739
740 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
741 NV_SOR_SUPER_STATE1_ATTACHED_NO);
742
743 /*
744 * Enable display2sor clock at least 2 cycles before DC start,
745 * to clear sor internal valid signal.
746 */
747
748 /* Stop dc for 3 cycles */
749 WRITEL(0, &disp_ctrl->disp.disp_win_opt);
750 WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
751 udelay(FRAME_IN_MS * 1000 * 3);
752
753 /* Attach head */
754 tegra_dc_sor_update(sor);
755 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
756 NV_SOR_SUPER_STATE1_ATTACHED_YES);
757 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
758 NV_SOR_SUPER_STATE1_ATTACHED_YES |
759 NV_SOR_SUPER_STATE1_ASY_HEAD_OP_AWAKE |
760 NV_SOR_SUPER_STATE1_ASY_ORMODE_NORMAL);
761 tegra_dc_sor_super_update(sor);
762
763 /* wait for another 5 cycles */
764 udelay(FRAME_IN_MS * 1000 * 5);
765
766 /* Re-enable dc */
767 WRITEL(READ_MUX_ACTIVE | WRITE_MUX_ACTIVE,
768 &disp_ctrl->cmd.state_access);
769 WRITEL(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt);
770
771 WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd);
772 WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
773
774 if (tegra_dc_sor_poll_register(sor, NV_SOR_TEST,
775 NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK,
776 NV_SOR_TEST_ACT_HEAD_OPMODE_AWAKE,
777 100, TEGRA_SOR_ATTACH_TIMEOUT_MS * 1000))
778 printk(BIOS_ERR, "dc timeout waiting for OPMOD = AWAKE\n");
779 else
780 printk(BIOS_INFO, "%s: sor is attached\n", __func__);
781
782#if DEBUG_SOR
783 dump_sor_reg(sor);
784#endif
785}
786
787void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
788 const struct tegra_dc_dp_link_config *link_cfg)
789{
790 tegra_sor_writel(sor, NV_SOR_LANE_DRIVE_CURRENT(sor->portnum),
791 link_cfg->drive_current);
792 tegra_sor_writel(sor, NV_SOR_PR(sor->portnum),
793 link_cfg->preemphasis);
794 tegra_sor_writel(sor, NV_SOR_POSTCURSOR(sor->portnum),
795 link_cfg->postcursor);
796 tegra_sor_writel(sor, NV_SOR_LVDS, 0);
797
798 tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw);
799 tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count);
800
801 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
802 NV_SOR_DP_PADCTL_TX_PU_ENABLE |
803 NV_SOR_DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK,
804 NV_SOR_DP_PADCTL_TX_PU_ENABLE |
805 2 << NV_SOR_DP_PADCTL_TX_PU_VALUE_SHIFT);
806
807 /* Precharge */
808 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
809 0xf0, 0xf0);
810 udelay(20);
811
812 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
813 0xf0, 0x0);
814}
815
816void tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor)
817{
818 u32 drive_current = 0;
819 u32 pre_emphasis = 0;
820
821 /* Set to a known-good pre-calibrated setting */
822 switch (sor->link_cfg->link_bw) {
823 case SOR_LINK_SPEED_G1_62:
824 case SOR_LINK_SPEED_G2_7:
825 drive_current = 0x13131313;
826 pre_emphasis = 0;
827 break;
828 case SOR_LINK_SPEED_G5_4:
829 printk(BIOS_WARNING, "T1xx does not support 5.4G link"
830 " clock.\n");
831 default:
832 printk(BIOS_WARNING, "Invalid sor link bandwidth: %d\n",
833 sor->link_cfg->link_bw);
834 return;
835 }
836
837 tegra_sor_writel(sor, NV_SOR_LANE_DRIVE_CURRENT(sor->portnum),
838 drive_current);
839 tegra_sor_writel(sor, NV_SOR_PR(sor->portnum), pre_emphasis);
840}
841
842void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor)
843{
844 u32 pad_ctrl = 0;
845 int err = 0;
846
847 switch (sor->link_cfg->lane_count) {
848 case 4:
849 pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO |
850 NV_SOR_DP_PADCTL_PD_TXD_1_NO |
851 NV_SOR_DP_PADCTL_PD_TXD_2_NO |
852 NV_SOR_DP_PADCTL_PD_TXD_3_NO);
853 break;
854 case 2:
855 pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO |
856 NV_SOR_DP_PADCTL_PD_TXD_1_NO |
857 NV_SOR_DP_PADCTL_PD_TXD_2_YES |
858 NV_SOR_DP_PADCTL_PD_TXD_3_YES);
859 break;
860 case 1:
861 pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO |
862 NV_SOR_DP_PADCTL_PD_TXD_1_YES |
863 NV_SOR_DP_PADCTL_PD_TXD_2_YES |
864 NV_SOR_DP_PADCTL_PD_TXD_3_YES);
865 break;
866 default:
867 printk(BIOS_ERR, "Invalid sor lane count: %u\n",
868 sor->link_cfg->lane_count);
869 return;
870 }
871
872 pad_ctrl |= NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN;
873 tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), pad_ctrl);
874
875 err = tegra_dc_sor_enable_lane_sequencer(sor, 0, 0);
876 if (err) {
877 printk(BIOS_ERR,
878 "Wait for lane power down failed: %d\n", err);
879 return;
880 }
881}
882
883void tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor)
884{
885 const struct tegra_dc_dp_link_config *cfg = sor->link_cfg;
886 u32 val = 0;
887
888 switch (cfg->lane_count) {
889 case 4:
890 val |= (NV_SOR_DP_PADCTL_PD_TXD_3_NO |
891 NV_SOR_DP_PADCTL_PD_TXD_2_NO);
Arthur Heymansfff20212021-03-15 14:56:16 +0100892 fallthrough;
Patrick Georgi40a3e322015-06-22 19:41:29 +0200893 case 2:
894 val |= NV_SOR_DP_PADCTL_PD_TXD_1_NO;
Arthur Heymansfff20212021-03-15 14:56:16 +0100895 fallthrough;
Patrick Georgi40a3e322015-06-22 19:41:29 +0200896 case 1:
897 val |= NV_SOR_DP_PADCTL_PD_TXD_0_NO;
898 break;
899 default:
900 printk(BIOS_ERR,
901 "dp: invalid lane number %d\n", cfg->lane_count);
902 return;
903 }
904
905 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
906 (0xf << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT),
907 (val << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT));
908 udelay(100);
909 tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
910 (0xf << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT), 0);
911}
912
913static u32 tegra_dc_poll_register(void *reg,
914 u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_us)
915{
916 u32 temp = timeout_us;
917 u32 reg_val = 0;
918
919 do {
920 udelay(poll_interval_us);
921 reg_val = READL(reg);
922 if (timeout_us > poll_interval_us)
923 timeout_us -= poll_interval_us;
924 else
925 break;
926 } while ((reg_val & mask) != exp_val);
927
928 if ((reg_val & mask) == exp_val)
929 return 0; /* success */
930
931 return temp;
932}
933
934static void tegra_dc_sor_general_act(struct display_controller *disp_ctrl)
935{
936 WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
937
938 if (tegra_dc_poll_register(&disp_ctrl->cmd.state_ctrl,
939 GENERAL_ACT_REQ, 0, 100,
940 TEGRA_DC_POLL_TIMEOUT_MS*1000))
941 printk(BIOS_ERR,
942 "dc timeout waiting for DC to stop\n");
943}
944
945static struct tegra_dc_mode min_mode = {
946 .h_ref_to_sync = 0,
947 .v_ref_to_sync = 1,
948 .h_sync_width = 1,
949 .v_sync_width = 1,
950 .h_back_porch = 20,
951 .v_back_porch = 0,
952 .h_active = 16,
953 .v_active = 16,
954 .h_front_porch = 1,
955 .v_front_porch = 2,
956};
957
958/* Disable windows and set minimum raster timings */
959static void
960tegra_dc_sor_disable_win_short_raster(struct display_controller *disp_ctrl,
961 int *dc_reg_ctx)
962{
963 int selected_windows, i;
964
965 selected_windows = READL(&disp_ctrl->cmd.disp_win_header);
966
967 /* Store and clear window options */
968 for (i = 0; i < DC_N_WINDOWS; ++i) {
969 WRITEL(WINDOW_A_SELECT << i, &disp_ctrl->cmd.disp_win_header);
970 dc_reg_ctx[i] = READL(&disp_ctrl->win.win_opt);
971 WRITEL(0, &disp_ctrl->win.win_opt);
972 WRITEL(WIN_A_ACT_REQ << i, &disp_ctrl->cmd.state_ctrl);
973 }
974
975 WRITEL(selected_windows, &disp_ctrl->cmd.disp_win_header);
976
977 /* Store current raster timings and set minimum timings */
978 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.ref_to_sync);
979 WRITEL(min_mode.h_ref_to_sync | (min_mode.v_ref_to_sync << 16),
980 &disp_ctrl->disp.ref_to_sync);
981
982 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.sync_width);
983 WRITEL(min_mode.h_sync_width | (min_mode.v_sync_width << 16),
984 &disp_ctrl->disp.sync_width);
985
986 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.back_porch);
987 WRITEL(min_mode.h_back_porch |
988 min_mode.v_back_porch << 16,
989 &disp_ctrl->disp.back_porch);
990
991 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.front_porch);
992 WRITEL(min_mode.h_front_porch |
993 min_mode.v_front_porch << 16,
994 &disp_ctrl->disp.front_porch);
995
996 dc_reg_ctx[i++] = READL(&disp_ctrl->disp.disp_active);
997 WRITEL(min_mode.h_active | (min_mode.v_active << 16),
998 &disp_ctrl->disp.disp_active);
999
1000 WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
1001}
1002
1003/* Restore previous windows status and raster timings */
1004static void
1005tegra_dc_sor_restore_win_and_raster(struct display_controller *disp_ctrl,
1006 int *dc_reg_ctx)
1007{
1008 int selected_windows, i;
1009
1010 selected_windows = READL(&disp_ctrl->cmd.disp_win_header);
1011
1012 for (i = 0; i < DC_N_WINDOWS; ++i) {
1013 WRITEL(WINDOW_A_SELECT << i, &disp_ctrl->cmd.disp_win_header);
1014 WRITEL(dc_reg_ctx[i], &disp_ctrl->win.win_opt);
1015 WRITEL(WIN_A_ACT_REQ << i, &disp_ctrl->cmd.state_ctrl);
1016 }
1017
1018 WRITEL(selected_windows, &disp_ctrl->cmd.disp_win_header);
1019
1020 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.ref_to_sync);
1021 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.sync_width);
1022 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.back_porch);
1023 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.front_porch);
1024 WRITEL(dc_reg_ctx[i++], &disp_ctrl->disp.disp_active);
1025
1026 WRITEL(GENERAL_UPDATE, &disp_ctrl->cmd.state_ctrl);
1027}
1028
1029static void tegra_dc_sor_enable_sor(struct tegra_dc_sor_data *sor, int enable)
1030{
1031 struct display_controller *disp_ctrl = (void *)sor->dc->base;
1032 u32 reg_val = READL(&disp_ctrl->disp.disp_win_opt);
1033
1034 reg_val = enable ? reg_val | SOR_ENABLE : reg_val & ~SOR_ENABLE;
1035 WRITEL(reg_val, &disp_ctrl->disp.disp_win_opt);
1036}
1037
1038void tegra_dc_detach(struct tegra_dc_sor_data *sor)
1039{
1040 struct display_controller *disp_ctrl = (void *)sor->dc->base;
1041 int dc_reg_ctx[DC_N_WINDOWS + 5];
1042 unsigned long dc_int_mask;
1043
1044 /* Sleep mode */
1045 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
1046 NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SLEEP |
1047 NV_SOR_SUPER_STATE1_ASY_ORMODE_SAFE |
1048 NV_SOR_SUPER_STATE1_ATTACHED_YES);
1049 tegra_dc_sor_super_update(sor);
1050
1051 tegra_dc_sor_disable_win_short_raster(disp_ctrl, dc_reg_ctx);
1052
1053 if (tegra_dc_sor_poll_register(sor, NV_SOR_TEST,
1054 NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK,
1055 NV_SOR_TEST_ACT_HEAD_OPMODE_SLEEP,
1056 100, TEGRA_SOR_ATTACH_TIMEOUT_MS*1000)) {
1057 printk(BIOS_ERR,
1058 "dc timeout waiting for OPMOD = SLEEP\n");
1059 }
1060
1061 tegra_sor_writel(sor, NV_SOR_SUPER_STATE1,
1062 NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SLEEP |
1063 NV_SOR_SUPER_STATE1_ASY_ORMODE_SAFE |
1064 NV_SOR_SUPER_STATE1_ATTACHED_NO);
1065
1066 /* Mask DC interrupts during the 2 dummy frames required for detach */
1067 dc_int_mask = READL(&disp_ctrl->cmd.int_mask);
1068 WRITEL(0, &disp_ctrl->cmd.int_mask);
1069
1070 /* Stop DC->SOR path */
1071 tegra_dc_sor_enable_sor(sor, 0);
1072 tegra_dc_sor_general_act(disp_ctrl);
1073
1074 /* Stop DC */
1075 WRITEL(DISP_CTRL_MODE_STOP, &disp_ctrl->cmd.disp_cmd);
1076 tegra_dc_sor_general_act(disp_ctrl);
1077
1078 tegra_dc_sor_restore_win_and_raster(disp_ctrl, dc_reg_ctx);
1079
1080 WRITEL(dc_int_mask, &disp_ctrl->cmd.int_mask);
1081}