blob: 22a54434a757a77bc1ccb345a2dcfd32c3defbb4 [file] [log] [blame]
Thierry Reding6b6b6042013-11-15 16:06:05 +01001/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
Thierry Redingb2992212015-10-01 14:25:03 +020010#include <linux/clk-provider.h>
Thierry Redinga82752e2014-01-31 10:02:15 +010011#include <linux/debugfs.h>
Thierry Reding6fad8f62014-11-28 15:41:34 +010012#include <linux/gpio.h>
Thierry Reding6b6b6042013-11-15 16:06:05 +010013#include <linux/io.h>
Thierry Reding459cc2c2015-07-30 10:34:24 +020014#include <linux/of_device.h>
Thierry Reding6b6b6042013-11-15 16:06:05 +010015#include <linux/platform_device.h>
Thierry Redingaaff8bd2015-08-07 16:04:54 +020016#include <linux/pm_runtime.h>
Thierry Reding459cc2c2015-07-30 10:34:24 +020017#include <linux/regulator/consumer.h>
Thierry Reding6b6b6042013-11-15 16:06:05 +010018#include <linux/reset.h>
Thierry Reding306a7f92014-07-17 13:17:24 +020019
Thierry Reding72323982014-07-11 13:19:06 +020020#include <soc/tegra/pmc.h>
Thierry Reding6b6b6042013-11-15 16:06:05 +010021
Thierry Reding8e2988a72018-12-03 15:46:03 +010022#include <sound/hda_verbs.h>
23
Thierry Reding4aa3df72014-11-24 16:27:13 +010024#include <drm/drm_atomic_helper.h>
Thierry Reding6b6b6042013-11-15 16:06:05 +010025#include <drm/drm_dp_helper.h>
Thierry Reding6fad8f62014-11-28 15:41:34 +010026#include <drm/drm_panel.h>
Thierry Reding36e90222017-10-12 19:14:21 +020027#include <drm/drm_scdc_helper.h>
Thierry Reding6b6b6042013-11-15 16:06:05 +010028
29#include "dc.h"
30#include "drm.h"
31#include "sor.h"
Thierry Reding932f6522017-08-15 15:41:14 +020032#include "trace.h"
Thierry Reding6b6b6042013-11-15 16:06:05 +010033
Thierry Redingc57997b2017-10-12 19:12:57 +020034/*
35 * XXX Remove this after the commit adding it to soc/tegra/pmc.h has been
36 * merged. Having this around after the commit is merged should be safe since
37 * the preprocessor will effectively replace all occurrences and therefore no
38 * duplicate will be defined.
39 */
40#define TEGRA_IO_PAD_HDMI_DP0 26
41
Thierry Reding459cc2c2015-07-30 10:34:24 +020042#define SOR_REKEY 0x38
43
44struct tegra_sor_hdmi_settings {
45 unsigned long frequency;
46
47 u8 vcocap;
Thierry Redingc57997b2017-10-12 19:12:57 +020048 u8 filter;
Thierry Reding459cc2c2015-07-30 10:34:24 +020049 u8 ichpmp;
50 u8 loadadj;
Thierry Redingc57997b2017-10-12 19:12:57 +020051 u8 tmds_termadj;
52 u8 tx_pu_value;
53 u8 bg_temp_coef;
54 u8 bg_vref_level;
55 u8 avdd10_level;
56 u8 avdd14_level;
57 u8 sparepll;
Thierry Reding459cc2c2015-07-30 10:34:24 +020058
59 u8 drive_current[4];
60 u8 preemphasis[4];
61};
62
63#if 1
64static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
65 {
66 .frequency = 54000000,
67 .vcocap = 0x0,
Thierry Redingc57997b2017-10-12 19:12:57 +020068 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020069 .ichpmp = 0x1,
70 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020071 .tmds_termadj = 0x9,
72 .tx_pu_value = 0x10,
73 .bg_temp_coef = 0x3,
74 .bg_vref_level = 0x8,
75 .avdd10_level = 0x4,
76 .avdd14_level = 0x4,
77 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020078 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
79 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
80 }, {
81 .frequency = 75000000,
82 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020083 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020084 .ichpmp = 0x1,
85 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020086 .tmds_termadj = 0x9,
87 .tx_pu_value = 0x40,
88 .bg_temp_coef = 0x3,
89 .bg_vref_level = 0x8,
90 .avdd10_level = 0x4,
91 .avdd14_level = 0x4,
92 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020093 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
94 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
95 }, {
96 .frequency = 150000000,
97 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020098 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020099 .ichpmp = 0x1,
100 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200101 .tmds_termadj = 0x9,
102 .tx_pu_value = 0x66,
103 .bg_temp_coef = 0x3,
104 .bg_vref_level = 0x8,
105 .avdd10_level = 0x4,
106 .avdd14_level = 0x4,
107 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200108 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
109 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
110 }, {
111 .frequency = 300000000,
112 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200113 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200114 .ichpmp = 0x1,
115 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200116 .tmds_termadj = 0x9,
117 .tx_pu_value = 0x66,
118 .bg_temp_coef = 0x3,
119 .bg_vref_level = 0xa,
120 .avdd10_level = 0x4,
121 .avdd14_level = 0x4,
122 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200123 .drive_current = { 0x33, 0x3f, 0x3f, 0x3f },
124 .preemphasis = { 0x00, 0x17, 0x17, 0x17 },
125 }, {
126 .frequency = 600000000,
127 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200128 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200129 .ichpmp = 0x1,
130 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200131 .tmds_termadj = 0x9,
132 .tx_pu_value = 0x66,
133 .bg_temp_coef = 0x3,
134 .bg_vref_level = 0x8,
135 .avdd10_level = 0x4,
136 .avdd14_level = 0x4,
137 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200138 .drive_current = { 0x33, 0x3f, 0x3f, 0x3f },
139 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
140 },
141};
142#else
143static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
144 {
145 .frequency = 75000000,
146 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200147 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200148 .ichpmp = 0x1,
149 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200150 .tmds_termadj = 0x9,
151 .tx_pu_value = 0x40,
152 .bg_temp_coef = 0x3,
153 .bg_vref_level = 0x8,
154 .avdd10_level = 0x4,
155 .avdd14_level = 0x4,
156 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200157 .drive_current = { 0x29, 0x29, 0x29, 0x29 },
158 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
159 }, {
160 .frequency = 150000000,
161 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200162 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200163 .ichpmp = 0x1,
164 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200165 .tmds_termadj = 0x9,
166 .tx_pu_value = 0x66,
167 .bg_temp_coef = 0x3,
168 .bg_vref_level = 0x8,
169 .avdd10_level = 0x4,
170 .avdd14_level = 0x4,
171 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200172 .drive_current = { 0x30, 0x37, 0x37, 0x37 },
173 .preemphasis = { 0x01, 0x02, 0x02, 0x02 },
174 }, {
175 .frequency = 300000000,
176 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200177 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200178 .ichpmp = 0x6,
179 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200180 .tmds_termadj = 0x9,
181 .tx_pu_value = 0x66,
182 .bg_temp_coef = 0x3,
183 .bg_vref_level = 0xf,
184 .avdd10_level = 0x4,
185 .avdd14_level = 0x4,
186 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200187 .drive_current = { 0x30, 0x37, 0x37, 0x37 },
188 .preemphasis = { 0x10, 0x3e, 0x3e, 0x3e },
189 }, {
190 .frequency = 600000000,
191 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200192 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200193 .ichpmp = 0xa,
194 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200195 .tmds_termadj = 0xb,
196 .tx_pu_value = 0x66,
197 .bg_temp_coef = 0x3,
198 .bg_vref_level = 0xe,
199 .avdd10_level = 0x4,
200 .avdd14_level = 0x4,
201 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200202 .drive_current = { 0x35, 0x3e, 0x3e, 0x3e },
203 .preemphasis = { 0x02, 0x3f, 0x3f, 0x3f },
204 },
205};
206#endif
207
Thierry Redingc57997b2017-10-12 19:12:57 +0200208static const struct tegra_sor_hdmi_settings tegra186_sor_hdmi_defaults[] = {
209 {
210 .frequency = 54000000,
211 .vcocap = 0,
212 .filter = 5,
213 .ichpmp = 5,
214 .loadadj = 3,
215 .tmds_termadj = 0xf,
216 .tx_pu_value = 0,
217 .bg_temp_coef = 3,
218 .bg_vref_level = 8,
219 .avdd10_level = 4,
220 .avdd14_level = 4,
221 .sparepll = 0x54,
222 .drive_current = { 0x3a, 0x3a, 0x3a, 0x33 },
223 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
224 }, {
225 .frequency = 75000000,
226 .vcocap = 1,
227 .filter = 5,
228 .ichpmp = 5,
229 .loadadj = 3,
230 .tmds_termadj = 0xf,
231 .tx_pu_value = 0,
232 .bg_temp_coef = 3,
233 .bg_vref_level = 8,
234 .avdd10_level = 4,
235 .avdd14_level = 4,
236 .sparepll = 0x44,
237 .drive_current = { 0x3a, 0x3a, 0x3a, 0x33 },
238 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
239 }, {
240 .frequency = 150000000,
241 .vcocap = 3,
242 .filter = 5,
243 .ichpmp = 5,
244 .loadadj = 3,
245 .tmds_termadj = 15,
246 .tx_pu_value = 0x66 /* 0 */,
247 .bg_temp_coef = 3,
248 .bg_vref_level = 8,
249 .avdd10_level = 4,
250 .avdd14_level = 4,
251 .sparepll = 0x00, /* 0x34 */
252 .drive_current = { 0x3a, 0x3a, 0x3a, 0x37 },
253 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
254 }, {
255 .frequency = 300000000,
256 .vcocap = 3,
257 .filter = 5,
258 .ichpmp = 5,
259 .loadadj = 3,
260 .tmds_termadj = 15,
261 .tx_pu_value = 64,
262 .bg_temp_coef = 3,
263 .bg_vref_level = 8,
264 .avdd10_level = 4,
265 .avdd14_level = 4,
266 .sparepll = 0x34,
267 .drive_current = { 0x3d, 0x3d, 0x3d, 0x33 },
268 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
269 }, {
270 .frequency = 600000000,
271 .vcocap = 3,
272 .filter = 5,
273 .ichpmp = 5,
274 .loadadj = 3,
275 .tmds_termadj = 12,
276 .tx_pu_value = 96,
277 .bg_temp_coef = 3,
278 .bg_vref_level = 8,
279 .avdd10_level = 4,
280 .avdd14_level = 4,
281 .sparepll = 0x34,
282 .drive_current = { 0x3d, 0x3d, 0x3d, 0x33 },
283 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
284 }
285};
286
Thierry Reding9b6c14b2018-09-21 12:27:46 +0200287static const struct tegra_sor_hdmi_settings tegra194_sor_hdmi_defaults[] = {
288 {
289 .frequency = 54000000,
290 .vcocap = 0,
291 .filter = 5,
292 .ichpmp = 5,
293 .loadadj = 3,
294 .tmds_termadj = 0xf,
295 .tx_pu_value = 0,
296 .bg_temp_coef = 3,
297 .bg_vref_level = 8,
298 .avdd10_level = 4,
299 .avdd14_level = 4,
300 .sparepll = 0x54,
301 .drive_current = { 0x3a, 0x3a, 0x3a, 0x33 },
302 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
303 }, {
304 .frequency = 75000000,
305 .vcocap = 1,
306 .filter = 5,
307 .ichpmp = 5,
308 .loadadj = 3,
309 .tmds_termadj = 0xf,
310 .tx_pu_value = 0,
311 .bg_temp_coef = 3,
312 .bg_vref_level = 8,
313 .avdd10_level = 4,
314 .avdd14_level = 4,
315 .sparepll = 0x44,
316 .drive_current = { 0x3a, 0x3a, 0x3a, 0x33 },
317 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
318 }, {
319 .frequency = 150000000,
320 .vcocap = 3,
321 .filter = 5,
322 .ichpmp = 5,
323 .loadadj = 3,
324 .tmds_termadj = 15,
325 .tx_pu_value = 0x66 /* 0 */,
326 .bg_temp_coef = 3,
327 .bg_vref_level = 8,
328 .avdd10_level = 4,
329 .avdd14_level = 4,
330 .sparepll = 0x00, /* 0x34 */
331 .drive_current = { 0x3a, 0x3a, 0x3a, 0x37 },
332 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
333 }, {
334 .frequency = 300000000,
335 .vcocap = 3,
336 .filter = 5,
337 .ichpmp = 5,
338 .loadadj = 3,
339 .tmds_termadj = 15,
340 .tx_pu_value = 64,
341 .bg_temp_coef = 3,
342 .bg_vref_level = 8,
343 .avdd10_level = 4,
344 .avdd14_level = 4,
345 .sparepll = 0x34,
346 .drive_current = { 0x3d, 0x3d, 0x3d, 0x33 },
347 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
348 }, {
349 .frequency = 600000000,
350 .vcocap = 3,
351 .filter = 5,
352 .ichpmp = 5,
353 .loadadj = 3,
354 .tmds_termadj = 12,
355 .tx_pu_value = 96,
356 .bg_temp_coef = 3,
357 .bg_vref_level = 8,
358 .avdd10_level = 4,
359 .avdd14_level = 4,
360 .sparepll = 0x34,
361 .drive_current = { 0x3d, 0x3d, 0x3d, 0x33 },
362 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
363 }
364};
365
Thierry Reding880cee02017-10-12 19:04:17 +0200366struct tegra_sor_regs {
367 unsigned int head_state0;
368 unsigned int head_state1;
369 unsigned int head_state2;
370 unsigned int head_state3;
371 unsigned int head_state4;
372 unsigned int head_state5;
373 unsigned int pll0;
374 unsigned int pll1;
375 unsigned int pll2;
376 unsigned int pll3;
377 unsigned int dp_padctl0;
378 unsigned int dp_padctl2;
379};
380
Thierry Reding459cc2c2015-07-30 10:34:24 +0200381struct tegra_sor_soc {
382 bool supports_edp;
383 bool supports_lvds;
384 bool supports_hdmi;
385 bool supports_dp;
386
Thierry Reding880cee02017-10-12 19:04:17 +0200387 const struct tegra_sor_regs *regs;
Thierry Redingc57997b2017-10-12 19:12:57 +0200388 bool has_nvdisplay;
Thierry Reding880cee02017-10-12 19:04:17 +0200389
Thierry Reding459cc2c2015-07-30 10:34:24 +0200390 const struct tegra_sor_hdmi_settings *settings;
391 unsigned int num_settings;
Thierry Reding30b49432015-08-03 15:50:32 +0200392
393 const u8 *xbar_cfg;
Thierry Reding459cc2c2015-07-30 10:34:24 +0200394};
395
396struct tegra_sor;
397
398struct tegra_sor_ops {
399 const char *name;
400 int (*probe)(struct tegra_sor *sor);
401 int (*remove)(struct tegra_sor *sor);
402};
403
Thierry Reding6b6b6042013-11-15 16:06:05 +0100404struct tegra_sor {
405 struct host1x_client client;
406 struct tegra_output output;
407 struct device *dev;
408
Thierry Reding459cc2c2015-07-30 10:34:24 +0200409 const struct tegra_sor_soc *soc;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100410 void __iomem *regs;
Thierry Redingc57997b2017-10-12 19:12:57 +0200411 unsigned int index;
Thierry Reding8e2988a72018-12-03 15:46:03 +0100412 unsigned int irq;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100413
414 struct reset_control *rst;
415 struct clk *clk_parent;
416 struct clk *clk_safe;
Thierry Redinge1335e22017-10-12 17:53:11 +0200417 struct clk *clk_out;
418 struct clk *clk_pad;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100419 struct clk *clk_dp;
420 struct clk *clk;
421
Thierry Reding9542c232015-07-08 13:39:09 +0200422 struct drm_dp_aux *aux;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100423
Thierry Redingdab16332015-01-26 16:04:08 +0100424 struct drm_info_list *debugfs_files;
Thierry Reding459cc2c2015-07-30 10:34:24 +0200425
426 const struct tegra_sor_ops *ops;
Thierry Redingc57997b2017-10-12 19:12:57 +0200427 enum tegra_io_pad pad;
Thierry Reding459cc2c2015-07-30 10:34:24 +0200428
429 /* for HDMI 2.0 */
430 struct tegra_sor_hdmi_settings *settings;
431 unsigned int num_settings;
432
433 struct regulator *avdd_io_supply;
434 struct regulator *vdd_pll_supply;
435 struct regulator *hdmi_supply;
Thierry Reding36e90222017-10-12 19:14:21 +0200436
437 struct delayed_work scdc;
438 bool scdc_enabled;
Thierry Reding8e2988a72018-12-03 15:46:03 +0100439
440 struct {
441 unsigned int sample_rate;
442 unsigned int channels;
443 } audio;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100444};
445
Thierry Redingc31efa72015-09-08 16:09:22 +0200446struct tegra_sor_state {
447 struct drm_connector_state base;
448
Thierry Reding36e90222017-10-12 19:14:21 +0200449 unsigned int link_speed;
450 unsigned long pclk;
Thierry Redingc31efa72015-09-08 16:09:22 +0200451 unsigned int bpc;
452};
453
454static inline struct tegra_sor_state *
455to_sor_state(struct drm_connector_state *state)
456{
457 return container_of(state, struct tegra_sor_state, base);
458}
459
Thierry Reding34fa1832014-06-05 16:31:10 +0200460struct tegra_sor_config {
461 u32 bits_per_pixel;
462
463 u32 active_polarity;
464 u32 active_count;
465 u32 tu_size;
466 u32 active_frac;
467 u32 watermark;
Thierry Reding7890b572014-06-05 16:12:46 +0200468
469 u32 hblank_symbols;
470 u32 vblank_symbols;
Thierry Reding34fa1832014-06-05 16:31:10 +0200471};
472
Thierry Reding6b6b6042013-11-15 16:06:05 +0100473static inline struct tegra_sor *
474host1x_client_to_sor(struct host1x_client *client)
475{
476 return container_of(client, struct tegra_sor, client);
477}
478
479static inline struct tegra_sor *to_sor(struct tegra_output *output)
480{
481 return container_of(output, struct tegra_sor, output);
482}
483
Thierry Reding5c5f1302017-08-15 15:41:09 +0200484static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned int offset)
Thierry Reding6b6b6042013-11-15 16:06:05 +0100485{
Thierry Reding932f6522017-08-15 15:41:14 +0200486 u32 value = readl(sor->regs + (offset << 2));
487
488 trace_sor_readl(sor->dev, offset, value);
489
490 return value;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100491}
492
Thierry Reding28fe2072015-01-26 16:02:48 +0100493static inline void tegra_sor_writel(struct tegra_sor *sor, u32 value,
Thierry Reding5c5f1302017-08-15 15:41:09 +0200494 unsigned int offset)
Thierry Reding6b6b6042013-11-15 16:06:05 +0100495{
Thierry Reding932f6522017-08-15 15:41:14 +0200496 trace_sor_writel(sor->dev, offset, value);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100497 writel(value, sor->regs + (offset << 2));
498}
499
Thierry Reding25bb2ce2015-08-03 14:23:29 +0200500static int tegra_sor_set_parent_clock(struct tegra_sor *sor, struct clk *parent)
501{
502 int err;
503
504 clk_disable_unprepare(sor->clk);
505
Thierry Redinge1335e22017-10-12 17:53:11 +0200506 err = clk_set_parent(sor->clk_out, parent);
Thierry Reding25bb2ce2015-08-03 14:23:29 +0200507 if (err < 0)
508 return err;
509
510 err = clk_prepare_enable(sor->clk);
511 if (err < 0)
512 return err;
513
514 return 0;
515}
516
Thierry Redinge1335e22017-10-12 17:53:11 +0200517struct tegra_clk_sor_pad {
Thierry Redingb2992212015-10-01 14:25:03 +0200518 struct clk_hw hw;
519 struct tegra_sor *sor;
520};
521
Thierry Redinge1335e22017-10-12 17:53:11 +0200522static inline struct tegra_clk_sor_pad *to_pad(struct clk_hw *hw)
Thierry Redingb2992212015-10-01 14:25:03 +0200523{
Thierry Redinge1335e22017-10-12 17:53:11 +0200524 return container_of(hw, struct tegra_clk_sor_pad, hw);
Thierry Redingb2992212015-10-01 14:25:03 +0200525}
526
Thierry Redinge1335e22017-10-12 17:53:11 +0200527static const char * const tegra_clk_sor_pad_parents[] = {
Thierry Redingb2992212015-10-01 14:25:03 +0200528 "pll_d2_out0", "pll_dp"
529};
530
Thierry Redinge1335e22017-10-12 17:53:11 +0200531static int tegra_clk_sor_pad_set_parent(struct clk_hw *hw, u8 index)
Thierry Redingb2992212015-10-01 14:25:03 +0200532{
Thierry Redinge1335e22017-10-12 17:53:11 +0200533 struct tegra_clk_sor_pad *pad = to_pad(hw);
534 struct tegra_sor *sor = pad->sor;
Thierry Redingb2992212015-10-01 14:25:03 +0200535 u32 value;
536
537 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
538 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
539
540 switch (index) {
541 case 0:
542 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK;
543 break;
544
545 case 1:
546 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
547 break;
548 }
549
550 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
551
552 return 0;
553}
554
Thierry Redinge1335e22017-10-12 17:53:11 +0200555static u8 tegra_clk_sor_pad_get_parent(struct clk_hw *hw)
Thierry Redingb2992212015-10-01 14:25:03 +0200556{
Thierry Redinge1335e22017-10-12 17:53:11 +0200557 struct tegra_clk_sor_pad *pad = to_pad(hw);
558 struct tegra_sor *sor = pad->sor;
Thierry Redingb2992212015-10-01 14:25:03 +0200559 u8 parent = U8_MAX;
560 u32 value;
561
562 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
563
564 switch (value & SOR_CLK_CNTRL_DP_CLK_SEL_MASK) {
565 case SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK:
566 case SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_PCLK:
567 parent = 0;
568 break;
569
570 case SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK:
571 case SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_DPCLK:
572 parent = 1;
573 break;
574 }
575
576 return parent;
577}
578
Thierry Redinge1335e22017-10-12 17:53:11 +0200579static const struct clk_ops tegra_clk_sor_pad_ops = {
580 .set_parent = tegra_clk_sor_pad_set_parent,
581 .get_parent = tegra_clk_sor_pad_get_parent,
Thierry Redingb2992212015-10-01 14:25:03 +0200582};
583
Thierry Redinge1335e22017-10-12 17:53:11 +0200584static struct clk *tegra_clk_sor_pad_register(struct tegra_sor *sor,
585 const char *name)
Thierry Redingb2992212015-10-01 14:25:03 +0200586{
Thierry Redinge1335e22017-10-12 17:53:11 +0200587 struct tegra_clk_sor_pad *pad;
Thierry Redingb2992212015-10-01 14:25:03 +0200588 struct clk_init_data init;
589 struct clk *clk;
590
Thierry Redinge1335e22017-10-12 17:53:11 +0200591 pad = devm_kzalloc(sor->dev, sizeof(*pad), GFP_KERNEL);
592 if (!pad)
Thierry Redingb2992212015-10-01 14:25:03 +0200593 return ERR_PTR(-ENOMEM);
594
Thierry Redinge1335e22017-10-12 17:53:11 +0200595 pad->sor = sor;
Thierry Redingb2992212015-10-01 14:25:03 +0200596
597 init.name = name;
598 init.flags = 0;
Thierry Redinge1335e22017-10-12 17:53:11 +0200599 init.parent_names = tegra_clk_sor_pad_parents;
600 init.num_parents = ARRAY_SIZE(tegra_clk_sor_pad_parents);
601 init.ops = &tegra_clk_sor_pad_ops;
Thierry Redingb2992212015-10-01 14:25:03 +0200602
Thierry Redinge1335e22017-10-12 17:53:11 +0200603 pad->hw.init = &init;
Thierry Redingb2992212015-10-01 14:25:03 +0200604
Thierry Redinge1335e22017-10-12 17:53:11 +0200605 clk = devm_clk_register(sor->dev, &pad->hw);
Thierry Redingb2992212015-10-01 14:25:03 +0200606
607 return clk;
608}
609
Thierry Reding6b6b6042013-11-15 16:06:05 +0100610static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
611 struct drm_dp_link *link)
612{
Thierry Reding6b6b6042013-11-15 16:06:05 +0100613 unsigned int i;
614 u8 pattern;
Thierry Reding28fe2072015-01-26 16:02:48 +0100615 u32 value;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100616 int err;
617
618 /* setup lane parameters */
619 value = SOR_LANE_DRIVE_CURRENT_LANE3(0x40) |
620 SOR_LANE_DRIVE_CURRENT_LANE2(0x40) |
621 SOR_LANE_DRIVE_CURRENT_LANE1(0x40) |
622 SOR_LANE_DRIVE_CURRENT_LANE0(0x40);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200623 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100624
625 value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) |
626 SOR_LANE_PREEMPHASIS_LANE2(0x0f) |
627 SOR_LANE_PREEMPHASIS_LANE1(0x0f) |
628 SOR_LANE_PREEMPHASIS_LANE0(0x0f);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200629 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100630
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200631 value = SOR_LANE_POSTCURSOR_LANE3(0x00) |
632 SOR_LANE_POSTCURSOR_LANE2(0x00) |
633 SOR_LANE_POSTCURSOR_LANE1(0x00) |
634 SOR_LANE_POSTCURSOR_LANE0(0x00);
635 tegra_sor_writel(sor, value, SOR_LANE_POSTCURSOR0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100636
637 /* disable LVDS mode */
638 tegra_sor_writel(sor, 0, SOR_LVDS);
639
Thierry Reding880cee02017-10-12 19:04:17 +0200640 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100641 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
642 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
643 value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */
Thierry Reding880cee02017-10-12 19:04:17 +0200644 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100645
Thierry Reding880cee02017-10-12 19:04:17 +0200646 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100647 value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
648 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0;
Thierry Reding880cee02017-10-12 19:04:17 +0200649 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100650
651 usleep_range(10, 100);
652
Thierry Reding880cee02017-10-12 19:04:17 +0200653 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100654 value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
655 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
Thierry Reding880cee02017-10-12 19:04:17 +0200656 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100657
Thierry Reding9542c232015-07-08 13:39:09 +0200658 err = drm_dp_aux_prepare(sor->aux, DP_SET_ANSI_8B10B);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100659 if (err < 0)
660 return err;
661
662 for (i = 0, value = 0; i < link->num_lanes; i++) {
663 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
664 SOR_DP_TPG_SCRAMBLER_NONE |
665 SOR_DP_TPG_PATTERN_TRAIN1;
666 value = (value << 8) | lane;
667 }
668
669 tegra_sor_writel(sor, value, SOR_DP_TPG);
670
671 pattern = DP_TRAINING_PATTERN_1;
672
Thierry Reding9542c232015-07-08 13:39:09 +0200673 err = drm_dp_aux_train(sor->aux, link, pattern);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100674 if (err < 0)
675 return err;
676
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200677 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100678 value |= SOR_DP_SPARE_SEQ_ENABLE;
679 value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
680 value |= SOR_DP_SPARE_MACRO_SOR_CLK;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200681 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100682
683 for (i = 0, value = 0; i < link->num_lanes; i++) {
684 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
685 SOR_DP_TPG_SCRAMBLER_NONE |
686 SOR_DP_TPG_PATTERN_TRAIN2;
687 value = (value << 8) | lane;
688 }
689
690 tegra_sor_writel(sor, value, SOR_DP_TPG);
691
692 pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2;
693
Thierry Reding9542c232015-07-08 13:39:09 +0200694 err = drm_dp_aux_train(sor->aux, link, pattern);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100695 if (err < 0)
696 return err;
697
698 for (i = 0, value = 0; i < link->num_lanes; i++) {
699 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
700 SOR_DP_TPG_SCRAMBLER_GALIOS |
701 SOR_DP_TPG_PATTERN_NONE;
702 value = (value << 8) | lane;
703 }
704
705 tegra_sor_writel(sor, value, SOR_DP_TPG);
706
707 pattern = DP_TRAINING_PATTERN_DISABLE;
708
Thierry Reding9542c232015-07-08 13:39:09 +0200709 err = drm_dp_aux_train(sor->aux, link, pattern);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100710 if (err < 0)
711 return err;
712
713 return 0;
714}
715
716static void tegra_sor_super_update(struct tegra_sor *sor)
717{
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200718 tegra_sor_writel(sor, 0, SOR_SUPER_STATE0);
719 tegra_sor_writel(sor, 1, SOR_SUPER_STATE0);
720 tegra_sor_writel(sor, 0, SOR_SUPER_STATE0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100721}
722
723static void tegra_sor_update(struct tegra_sor *sor)
724{
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200725 tegra_sor_writel(sor, 0, SOR_STATE0);
726 tegra_sor_writel(sor, 1, SOR_STATE0);
727 tegra_sor_writel(sor, 0, SOR_STATE0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100728}
729
730static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout)
731{
Thierry Reding28fe2072015-01-26 16:02:48 +0100732 u32 value;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100733
734 value = tegra_sor_readl(sor, SOR_PWM_DIV);
735 value &= ~SOR_PWM_DIV_MASK;
736 value |= 0x400; /* period */
737 tegra_sor_writel(sor, value, SOR_PWM_DIV);
738
739 value = tegra_sor_readl(sor, SOR_PWM_CTL);
740 value &= ~SOR_PWM_CTL_DUTY_CYCLE_MASK;
741 value |= 0x400; /* duty cycle */
742 value &= ~SOR_PWM_CTL_CLK_SEL; /* clock source: PCLK */
743 value |= SOR_PWM_CTL_TRIGGER;
744 tegra_sor_writel(sor, value, SOR_PWM_CTL);
745
746 timeout = jiffies + msecs_to_jiffies(timeout);
747
748 while (time_before(jiffies, timeout)) {
749 value = tegra_sor_readl(sor, SOR_PWM_CTL);
750 if ((value & SOR_PWM_CTL_TRIGGER) == 0)
751 return 0;
752
753 usleep_range(25, 100);
754 }
755
756 return -ETIMEDOUT;
757}
758
759static int tegra_sor_attach(struct tegra_sor *sor)
760{
761 unsigned long value, timeout;
762
763 /* wake up in normal mode */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200764 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100765 value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE;
766 value |= SOR_SUPER_STATE_MODE_NORMAL;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200767 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100768 tegra_sor_super_update(sor);
769
770 /* attach */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200771 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100772 value |= SOR_SUPER_STATE_ATTACHED;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200773 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100774 tegra_sor_super_update(sor);
775
776 timeout = jiffies + msecs_to_jiffies(250);
777
778 while (time_before(jiffies, timeout)) {
779 value = tegra_sor_readl(sor, SOR_TEST);
780 if ((value & SOR_TEST_ATTACHED) != 0)
781 return 0;
782
783 usleep_range(25, 100);
784 }
785
786 return -ETIMEDOUT;
787}
788
789static int tegra_sor_wakeup(struct tegra_sor *sor)
790{
Thierry Reding6b6b6042013-11-15 16:06:05 +0100791 unsigned long value, timeout;
792
Thierry Reding6b6b6042013-11-15 16:06:05 +0100793 timeout = jiffies + msecs_to_jiffies(250);
794
795 /* wait for head to wake up */
796 while (time_before(jiffies, timeout)) {
797 value = tegra_sor_readl(sor, SOR_TEST);
798 value &= SOR_TEST_HEAD_MODE_MASK;
799
800 if (value == SOR_TEST_HEAD_MODE_AWAKE)
801 return 0;
802
803 usleep_range(25, 100);
804 }
805
806 return -ETIMEDOUT;
807}
808
809static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
810{
Thierry Reding28fe2072015-01-26 16:02:48 +0100811 u32 value;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100812
813 value = tegra_sor_readl(sor, SOR_PWR);
814 value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU;
815 tegra_sor_writel(sor, value, SOR_PWR);
816
817 timeout = jiffies + msecs_to_jiffies(timeout);
818
819 while (time_before(jiffies, timeout)) {
820 value = tegra_sor_readl(sor, SOR_PWR);
821 if ((value & SOR_PWR_TRIGGER) == 0)
822 return 0;
823
824 usleep_range(25, 100);
825 }
826
827 return -ETIMEDOUT;
828}
829
Thierry Reding34fa1832014-06-05 16:31:10 +0200830struct tegra_sor_params {
831 /* number of link clocks per line */
832 unsigned int num_clocks;
833 /* ratio between input and output */
834 u64 ratio;
835 /* precision factor */
836 u64 precision;
837
838 unsigned int active_polarity;
839 unsigned int active_count;
840 unsigned int active_frac;
841 unsigned int tu_size;
842 unsigned int error;
843};
844
845static int tegra_sor_compute_params(struct tegra_sor *sor,
846 struct tegra_sor_params *params,
847 unsigned int tu_size)
848{
849 u64 active_sym, active_count, frac, approx;
850 u32 active_polarity, active_frac = 0;
851 const u64 f = params->precision;
852 s64 error;
853
854 active_sym = params->ratio * tu_size;
855 active_count = div_u64(active_sym, f) * f;
856 frac = active_sym - active_count;
857
858 /* fraction < 0.5 */
859 if (frac >= (f / 2)) {
860 active_polarity = 1;
861 frac = f - frac;
862 } else {
863 active_polarity = 0;
864 }
865
866 if (frac != 0) {
867 frac = div_u64(f * f, frac); /* 1/fraction */
868 if (frac <= (15 * f)) {
869 active_frac = div_u64(frac, f);
870
871 /* round up */
872 if (active_polarity)
873 active_frac++;
874 } else {
875 active_frac = active_polarity ? 1 : 15;
876 }
877 }
878
879 if (active_frac == 1)
880 active_polarity = 0;
881
882 if (active_polarity == 1) {
883 if (active_frac) {
884 approx = active_count + (active_frac * (f - 1)) * f;
885 approx = div_u64(approx, active_frac * f);
886 } else {
887 approx = active_count + f;
888 }
889 } else {
890 if (active_frac)
891 approx = active_count + div_u64(f, active_frac);
892 else
893 approx = active_count;
894 }
895
896 error = div_s64(active_sym - approx, tu_size);
897 error *= params->num_clocks;
898
Andrew Morton79211c82015-11-09 14:58:13 -0800899 if (error <= 0 && abs(error) < params->error) {
Thierry Reding34fa1832014-06-05 16:31:10 +0200900 params->active_count = div_u64(active_count, f);
901 params->active_polarity = active_polarity;
902 params->active_frac = active_frac;
Andrew Morton79211c82015-11-09 14:58:13 -0800903 params->error = abs(error);
Thierry Reding34fa1832014-06-05 16:31:10 +0200904 params->tu_size = tu_size;
905
906 if (error == 0)
907 return true;
908 }
909
910 return false;
911}
912
Thierry Redinga1983592015-07-21 16:46:52 +0200913static int tegra_sor_compute_config(struct tegra_sor *sor,
914 const struct drm_display_mode *mode,
915 struct tegra_sor_config *config,
916 struct drm_dp_link *link)
Thierry Reding34fa1832014-06-05 16:31:10 +0200917{
918 const u64 f = 100000, link_rate = link->rate * 1000;
919 const u64 pclk = mode->clock * 1000;
Thierry Reding7890b572014-06-05 16:12:46 +0200920 u64 input, output, watermark, num;
Thierry Reding34fa1832014-06-05 16:31:10 +0200921 struct tegra_sor_params params;
Thierry Reding34fa1832014-06-05 16:31:10 +0200922 u32 num_syms_per_line;
923 unsigned int i;
924
925 if (!link_rate || !link->num_lanes || !pclk || !config->bits_per_pixel)
926 return -EINVAL;
927
928 output = link_rate * 8 * link->num_lanes;
929 input = pclk * config->bits_per_pixel;
930
931 if (input >= output)
932 return -ERANGE;
933
934 memset(&params, 0, sizeof(params));
935 params.ratio = div64_u64(input * f, output);
936 params.num_clocks = div_u64(link_rate * mode->hdisplay, pclk);
937 params.precision = f;
938 params.error = 64 * f;
939 params.tu_size = 64;
940
941 for (i = params.tu_size; i >= 32; i--)
942 if (tegra_sor_compute_params(sor, &params, i))
943 break;
944
945 if (params.active_frac == 0) {
946 config->active_polarity = 0;
947 config->active_count = params.active_count;
948
949 if (!params.active_polarity)
950 config->active_count--;
951
952 config->tu_size = params.tu_size;
953 config->active_frac = 1;
954 } else {
955 config->active_polarity = params.active_polarity;
956 config->active_count = params.active_count;
957 config->active_frac = params.active_frac;
958 config->tu_size = params.tu_size;
959 }
960
961 dev_dbg(sor->dev,
962 "polarity: %d active count: %d tu size: %d active frac: %d\n",
963 config->active_polarity, config->active_count,
964 config->tu_size, config->active_frac);
965
966 watermark = params.ratio * config->tu_size * (f - params.ratio);
967 watermark = div_u64(watermark, f);
968
969 watermark = div_u64(watermark + params.error, f);
970 config->watermark = watermark + (config->bits_per_pixel / 8) + 2;
971 num_syms_per_line = (mode->hdisplay * config->bits_per_pixel) *
972 (link->num_lanes * 8);
973
974 if (config->watermark > 30) {
975 config->watermark = 30;
976 dev_err(sor->dev,
977 "unable to compute TU size, forcing watermark to %u\n",
978 config->watermark);
979 } else if (config->watermark > num_syms_per_line) {
980 config->watermark = num_syms_per_line;
981 dev_err(sor->dev, "watermark too high, forcing to %u\n",
982 config->watermark);
983 }
984
Thierry Reding7890b572014-06-05 16:12:46 +0200985 /* compute the number of symbols per horizontal blanking interval */
986 num = ((mode->htotal - mode->hdisplay) - 7) * link_rate;
987 config->hblank_symbols = div_u64(num, pclk);
988
989 if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
990 config->hblank_symbols -= 3;
991
992 config->hblank_symbols -= 12 / link->num_lanes;
993
994 /* compute the number of symbols per vertical blanking interval */
995 num = (mode->hdisplay - 25) * link_rate;
996 config->vblank_symbols = div_u64(num, pclk);
997 config->vblank_symbols -= 36 / link->num_lanes + 4;
998
999 dev_dbg(sor->dev, "blank symbols: H:%u V:%u\n", config->hblank_symbols,
1000 config->vblank_symbols);
1001
Thierry Reding34fa1832014-06-05 16:31:10 +02001002 return 0;
1003}
1004
Thierry Reding402f6bc2015-07-21 16:48:19 +02001005static void tegra_sor_apply_config(struct tegra_sor *sor,
1006 const struct tegra_sor_config *config)
1007{
1008 u32 value;
1009
1010 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
1011 value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
1012 value |= SOR_DP_LINKCTL_TU_SIZE(config->tu_size);
1013 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
1014
1015 value = tegra_sor_readl(sor, SOR_DP_CONFIG0);
1016 value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
1017 value |= SOR_DP_CONFIG_WATERMARK(config->watermark);
1018
1019 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
1020 value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(config->active_count);
1021
1022 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
1023 value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(config->active_frac);
1024
1025 if (config->active_polarity)
1026 value |= SOR_DP_CONFIG_ACTIVE_SYM_POLARITY;
1027 else
1028 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY;
1029
1030 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
1031 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE;
1032 tegra_sor_writel(sor, value, SOR_DP_CONFIG0);
1033
1034 value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS);
1035 value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK;
1036 value |= config->hblank_symbols & 0xffff;
1037 tegra_sor_writel(sor, value, SOR_DP_AUDIO_HBLANK_SYMBOLS);
1038
1039 value = tegra_sor_readl(sor, SOR_DP_AUDIO_VBLANK_SYMBOLS);
1040 value &= ~SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK;
1041 value |= config->vblank_symbols & 0xffff;
1042 tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
1043}
1044
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001045static void tegra_sor_mode_set(struct tegra_sor *sor,
1046 const struct drm_display_mode *mode,
Thierry Redingc31efa72015-09-08 16:09:22 +02001047 struct tegra_sor_state *state)
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001048{
1049 struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc);
1050 unsigned int vbe, vse, hbe, hse, vbs, hbs;
1051 u32 value;
1052
1053 value = tegra_sor_readl(sor, SOR_STATE1);
1054 value &= ~SOR_STATE_ASY_PIXELDEPTH_MASK;
1055 value &= ~SOR_STATE_ASY_CRC_MODE_MASK;
1056 value &= ~SOR_STATE_ASY_OWNER_MASK;
1057
1058 value |= SOR_STATE_ASY_CRC_MODE_COMPLETE |
1059 SOR_STATE_ASY_OWNER(dc->pipe + 1);
1060
1061 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
1062 value &= ~SOR_STATE_ASY_HSYNCPOL;
1063
1064 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1065 value |= SOR_STATE_ASY_HSYNCPOL;
1066
1067 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
1068 value &= ~SOR_STATE_ASY_VSYNCPOL;
1069
1070 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1071 value |= SOR_STATE_ASY_VSYNCPOL;
1072
Thierry Redingc31efa72015-09-08 16:09:22 +02001073 switch (state->bpc) {
1074 case 16:
1075 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_48_444;
1076 break;
1077
1078 case 12:
1079 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_36_444;
1080 break;
1081
1082 case 10:
1083 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_30_444;
1084 break;
1085
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001086 case 8:
1087 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
1088 break;
1089
1090 case 6:
1091 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444;
1092 break;
1093
1094 default:
Thierry Redingc31efa72015-09-08 16:09:22 +02001095 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001096 break;
1097 }
1098
1099 tegra_sor_writel(sor, value, SOR_STATE1);
1100
1101 /*
1102 * TODO: The video timing programming below doesn't seem to match the
1103 * register definitions.
1104 */
1105
1106 value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
Thierry Reding880cee02017-10-12 19:04:17 +02001107 tegra_sor_writel(sor, value, sor->soc->regs->head_state1 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001108
1109 /* sync end = sync width - 1 */
1110 vse = mode->vsync_end - mode->vsync_start - 1;
1111 hse = mode->hsync_end - mode->hsync_start - 1;
1112
1113 value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
Thierry Reding880cee02017-10-12 19:04:17 +02001114 tegra_sor_writel(sor, value, sor->soc->regs->head_state2 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001115
1116 /* blank end = sync end + back porch */
1117 vbe = vse + (mode->vtotal - mode->vsync_end);
1118 hbe = hse + (mode->htotal - mode->hsync_end);
1119
1120 value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
Thierry Reding880cee02017-10-12 19:04:17 +02001121 tegra_sor_writel(sor, value, sor->soc->regs->head_state3 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001122
1123 /* blank start = blank end + active */
1124 vbs = vbe + mode->vdisplay;
1125 hbs = hbe + mode->hdisplay;
1126
1127 value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
Thierry Reding880cee02017-10-12 19:04:17 +02001128 tegra_sor_writel(sor, value, sor->soc->regs->head_state4 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001129
1130 /* XXX interlacing support */
Thierry Reding880cee02017-10-12 19:04:17 +02001131 tegra_sor_writel(sor, 0x001, sor->soc->regs->head_state5 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001132}
1133
Thierry Reding6fad8f62014-11-28 15:41:34 +01001134static int tegra_sor_detach(struct tegra_sor *sor)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001135{
Thierry Reding6fad8f62014-11-28 15:41:34 +01001136 unsigned long value, timeout;
1137
1138 /* switch to safe mode */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001139 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001140 value &= ~SOR_SUPER_STATE_MODE_NORMAL;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001141 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001142 tegra_sor_super_update(sor);
1143
1144 timeout = jiffies + msecs_to_jiffies(250);
1145
1146 while (time_before(jiffies, timeout)) {
1147 value = tegra_sor_readl(sor, SOR_PWR);
1148 if (value & SOR_PWR_MODE_SAFE)
1149 break;
1150 }
1151
1152 if ((value & SOR_PWR_MODE_SAFE) == 0)
1153 return -ETIMEDOUT;
1154
1155 /* go to sleep */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001156 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001157 value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001158 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001159 tegra_sor_super_update(sor);
1160
1161 /* detach */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001162 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001163 value &= ~SOR_SUPER_STATE_ATTACHED;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001164 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001165 tegra_sor_super_update(sor);
1166
1167 timeout = jiffies + msecs_to_jiffies(250);
1168
1169 while (time_before(jiffies, timeout)) {
1170 value = tegra_sor_readl(sor, SOR_TEST);
1171 if ((value & SOR_TEST_ATTACHED) == 0)
1172 break;
1173
1174 usleep_range(25, 100);
1175 }
1176
1177 if ((value & SOR_TEST_ATTACHED) != 0)
1178 return -ETIMEDOUT;
1179
1180 return 0;
1181}
1182
1183static int tegra_sor_power_down(struct tegra_sor *sor)
1184{
1185 unsigned long value, timeout;
1186 int err;
1187
1188 value = tegra_sor_readl(sor, SOR_PWR);
1189 value &= ~SOR_PWR_NORMAL_STATE_PU;
1190 value |= SOR_PWR_TRIGGER;
1191 tegra_sor_writel(sor, value, SOR_PWR);
1192
1193 timeout = jiffies + msecs_to_jiffies(250);
1194
1195 while (time_before(jiffies, timeout)) {
1196 value = tegra_sor_readl(sor, SOR_PWR);
1197 if ((value & SOR_PWR_TRIGGER) == 0)
1198 return 0;
1199
1200 usleep_range(25, 100);
1201 }
1202
1203 if ((value & SOR_PWR_TRIGGER) != 0)
1204 return -ETIMEDOUT;
1205
Thierry Reding25bb2ce2015-08-03 14:23:29 +02001206 /* switch to safe parent clock */
1207 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
Thierry Redinge1335e22017-10-12 17:53:11 +02001208 if (err < 0) {
Thierry Reding6fad8f62014-11-28 15:41:34 +01001209 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
Thierry Redinge1335e22017-10-12 17:53:11 +02001210 return err;
1211 }
Thierry Reding6fad8f62014-11-28 15:41:34 +01001212
Thierry Reding880cee02017-10-12 19:04:17 +02001213 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001214 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
1215 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2);
Thierry Reding880cee02017-10-12 19:04:17 +02001216 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001217
1218 /* stop lane sequencer */
1219 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP |
1220 SOR_LANE_SEQ_CTL_POWER_STATE_DOWN;
1221 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
1222
1223 timeout = jiffies + msecs_to_jiffies(250);
1224
1225 while (time_before(jiffies, timeout)) {
1226 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
1227 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
1228 break;
1229
1230 usleep_range(25, 100);
1231 }
1232
1233 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0)
1234 return -ETIMEDOUT;
1235
Thierry Reding880cee02017-10-12 19:04:17 +02001236 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001237 value |= SOR_PLL2_PORT_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001238 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001239
1240 usleep_range(20, 100);
1241
Thierry Reding880cee02017-10-12 19:04:17 +02001242 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001243 value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
Thierry Reding880cee02017-10-12 19:04:17 +02001244 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001245
Thierry Reding880cee02017-10-12 19:04:17 +02001246 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001247 value |= SOR_PLL2_SEQ_PLLCAPPD;
1248 value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
Thierry Reding880cee02017-10-12 19:04:17 +02001249 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001250
1251 usleep_range(20, 100);
1252
1253 return 0;
1254}
1255
Thierry Reding6fad8f62014-11-28 15:41:34 +01001256static int tegra_sor_crc_wait(struct tegra_sor *sor, unsigned long timeout)
1257{
1258 u32 value;
1259
1260 timeout = jiffies + msecs_to_jiffies(timeout);
1261
1262 while (time_before(jiffies, timeout)) {
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001263 value = tegra_sor_readl(sor, SOR_CRCA);
1264 if (value & SOR_CRCA_VALID)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001265 return 0;
1266
1267 usleep_range(100, 200);
1268 }
1269
1270 return -ETIMEDOUT;
1271}
1272
Thierry Reding530239a2015-08-06 11:04:54 +02001273static int tegra_sor_show_crc(struct seq_file *s, void *data)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001274{
Thierry Reding530239a2015-08-06 11:04:54 +02001275 struct drm_info_node *node = s->private;
1276 struct tegra_sor *sor = node->info_ent->data;
Thierry Reding850bab42015-07-29 17:58:41 +02001277 struct drm_crtc *crtc = sor->output.encoder.crtc;
1278 struct drm_device *drm = node->minor->dev;
Thierry Reding530239a2015-08-06 11:04:54 +02001279 int err = 0;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001280 u32 value;
1281
Thierry Reding850bab42015-07-29 17:58:41 +02001282 drm_modeset_lock_all(drm);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001283
Thierry Reding850bab42015-07-29 17:58:41 +02001284 if (!crtc || !crtc->state->active) {
1285 err = -EBUSY;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001286 goto unlock;
1287 }
1288
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001289 value = tegra_sor_readl(sor, SOR_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001290 value &= ~SOR_STATE_ASY_CRC_MODE_MASK;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001291 tegra_sor_writel(sor, value, SOR_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001292
1293 value = tegra_sor_readl(sor, SOR_CRC_CNTRL);
1294 value |= SOR_CRC_CNTRL_ENABLE;
1295 tegra_sor_writel(sor, value, SOR_CRC_CNTRL);
1296
1297 value = tegra_sor_readl(sor, SOR_TEST);
1298 value &= ~SOR_TEST_CRC_POST_SERIALIZE;
1299 tegra_sor_writel(sor, value, SOR_TEST);
1300
1301 err = tegra_sor_crc_wait(sor, 100);
1302 if (err < 0)
1303 goto unlock;
1304
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001305 tegra_sor_writel(sor, SOR_CRCA_RESET, SOR_CRCA);
1306 value = tegra_sor_readl(sor, SOR_CRCB);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001307
Thierry Reding530239a2015-08-06 11:04:54 +02001308 seq_printf(s, "%08x\n", value);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001309
1310unlock:
Thierry Reding850bab42015-07-29 17:58:41 +02001311 drm_modeset_unlock_all(drm);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001312 return err;
1313}
1314
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001315#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
1316
1317static const struct debugfs_reg32 tegra_sor_regs[] = {
1318 DEBUGFS_REG32(SOR_CTXSW),
1319 DEBUGFS_REG32(SOR_SUPER_STATE0),
1320 DEBUGFS_REG32(SOR_SUPER_STATE1),
1321 DEBUGFS_REG32(SOR_STATE0),
1322 DEBUGFS_REG32(SOR_STATE1),
1323 DEBUGFS_REG32(SOR_HEAD_STATE0(0)),
1324 DEBUGFS_REG32(SOR_HEAD_STATE0(1)),
1325 DEBUGFS_REG32(SOR_HEAD_STATE1(0)),
1326 DEBUGFS_REG32(SOR_HEAD_STATE1(1)),
1327 DEBUGFS_REG32(SOR_HEAD_STATE2(0)),
1328 DEBUGFS_REG32(SOR_HEAD_STATE2(1)),
1329 DEBUGFS_REG32(SOR_HEAD_STATE3(0)),
1330 DEBUGFS_REG32(SOR_HEAD_STATE3(1)),
1331 DEBUGFS_REG32(SOR_HEAD_STATE4(0)),
1332 DEBUGFS_REG32(SOR_HEAD_STATE4(1)),
1333 DEBUGFS_REG32(SOR_HEAD_STATE5(0)),
1334 DEBUGFS_REG32(SOR_HEAD_STATE5(1)),
1335 DEBUGFS_REG32(SOR_CRC_CNTRL),
1336 DEBUGFS_REG32(SOR_DP_DEBUG_MVID),
1337 DEBUGFS_REG32(SOR_CLK_CNTRL),
1338 DEBUGFS_REG32(SOR_CAP),
1339 DEBUGFS_REG32(SOR_PWR),
1340 DEBUGFS_REG32(SOR_TEST),
1341 DEBUGFS_REG32(SOR_PLL0),
1342 DEBUGFS_REG32(SOR_PLL1),
1343 DEBUGFS_REG32(SOR_PLL2),
1344 DEBUGFS_REG32(SOR_PLL3),
1345 DEBUGFS_REG32(SOR_CSTM),
1346 DEBUGFS_REG32(SOR_LVDS),
1347 DEBUGFS_REG32(SOR_CRCA),
1348 DEBUGFS_REG32(SOR_CRCB),
1349 DEBUGFS_REG32(SOR_BLANK),
1350 DEBUGFS_REG32(SOR_SEQ_CTL),
1351 DEBUGFS_REG32(SOR_LANE_SEQ_CTL),
1352 DEBUGFS_REG32(SOR_SEQ_INST(0)),
1353 DEBUGFS_REG32(SOR_SEQ_INST(1)),
1354 DEBUGFS_REG32(SOR_SEQ_INST(2)),
1355 DEBUGFS_REG32(SOR_SEQ_INST(3)),
1356 DEBUGFS_REG32(SOR_SEQ_INST(4)),
1357 DEBUGFS_REG32(SOR_SEQ_INST(5)),
1358 DEBUGFS_REG32(SOR_SEQ_INST(6)),
1359 DEBUGFS_REG32(SOR_SEQ_INST(7)),
1360 DEBUGFS_REG32(SOR_SEQ_INST(8)),
1361 DEBUGFS_REG32(SOR_SEQ_INST(9)),
1362 DEBUGFS_REG32(SOR_SEQ_INST(10)),
1363 DEBUGFS_REG32(SOR_SEQ_INST(11)),
1364 DEBUGFS_REG32(SOR_SEQ_INST(12)),
1365 DEBUGFS_REG32(SOR_SEQ_INST(13)),
1366 DEBUGFS_REG32(SOR_SEQ_INST(14)),
1367 DEBUGFS_REG32(SOR_SEQ_INST(15)),
1368 DEBUGFS_REG32(SOR_PWM_DIV),
1369 DEBUGFS_REG32(SOR_PWM_CTL),
1370 DEBUGFS_REG32(SOR_VCRC_A0),
1371 DEBUGFS_REG32(SOR_VCRC_A1),
1372 DEBUGFS_REG32(SOR_VCRC_B0),
1373 DEBUGFS_REG32(SOR_VCRC_B1),
1374 DEBUGFS_REG32(SOR_CCRC_A0),
1375 DEBUGFS_REG32(SOR_CCRC_A1),
1376 DEBUGFS_REG32(SOR_CCRC_B0),
1377 DEBUGFS_REG32(SOR_CCRC_B1),
1378 DEBUGFS_REG32(SOR_EDATA_A0),
1379 DEBUGFS_REG32(SOR_EDATA_A1),
1380 DEBUGFS_REG32(SOR_EDATA_B0),
1381 DEBUGFS_REG32(SOR_EDATA_B1),
1382 DEBUGFS_REG32(SOR_COUNT_A0),
1383 DEBUGFS_REG32(SOR_COUNT_A1),
1384 DEBUGFS_REG32(SOR_COUNT_B0),
1385 DEBUGFS_REG32(SOR_COUNT_B1),
1386 DEBUGFS_REG32(SOR_DEBUG_A0),
1387 DEBUGFS_REG32(SOR_DEBUG_A1),
1388 DEBUGFS_REG32(SOR_DEBUG_B0),
1389 DEBUGFS_REG32(SOR_DEBUG_B1),
1390 DEBUGFS_REG32(SOR_TRIG),
1391 DEBUGFS_REG32(SOR_MSCHECK),
1392 DEBUGFS_REG32(SOR_XBAR_CTRL),
1393 DEBUGFS_REG32(SOR_XBAR_POL),
1394 DEBUGFS_REG32(SOR_DP_LINKCTL0),
1395 DEBUGFS_REG32(SOR_DP_LINKCTL1),
1396 DEBUGFS_REG32(SOR_LANE_DRIVE_CURRENT0),
1397 DEBUGFS_REG32(SOR_LANE_DRIVE_CURRENT1),
1398 DEBUGFS_REG32(SOR_LANE4_DRIVE_CURRENT0),
1399 DEBUGFS_REG32(SOR_LANE4_DRIVE_CURRENT1),
1400 DEBUGFS_REG32(SOR_LANE_PREEMPHASIS0),
1401 DEBUGFS_REG32(SOR_LANE_PREEMPHASIS1),
1402 DEBUGFS_REG32(SOR_LANE4_PREEMPHASIS0),
1403 DEBUGFS_REG32(SOR_LANE4_PREEMPHASIS1),
1404 DEBUGFS_REG32(SOR_LANE_POSTCURSOR0),
1405 DEBUGFS_REG32(SOR_LANE_POSTCURSOR1),
1406 DEBUGFS_REG32(SOR_DP_CONFIG0),
1407 DEBUGFS_REG32(SOR_DP_CONFIG1),
1408 DEBUGFS_REG32(SOR_DP_MN0),
1409 DEBUGFS_REG32(SOR_DP_MN1),
1410 DEBUGFS_REG32(SOR_DP_PADCTL0),
1411 DEBUGFS_REG32(SOR_DP_PADCTL1),
Thierry Redingc57997b2017-10-12 19:12:57 +02001412 DEBUGFS_REG32(SOR_DP_PADCTL2),
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001413 DEBUGFS_REG32(SOR_DP_DEBUG0),
1414 DEBUGFS_REG32(SOR_DP_DEBUG1),
1415 DEBUGFS_REG32(SOR_DP_SPARE0),
1416 DEBUGFS_REG32(SOR_DP_SPARE1),
1417 DEBUGFS_REG32(SOR_DP_AUDIO_CTRL),
1418 DEBUGFS_REG32(SOR_DP_AUDIO_HBLANK_SYMBOLS),
1419 DEBUGFS_REG32(SOR_DP_AUDIO_VBLANK_SYMBOLS),
1420 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_HEADER),
1421 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK0),
1422 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK1),
1423 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK2),
1424 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK3),
1425 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK4),
1426 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK5),
1427 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK6),
1428 DEBUGFS_REG32(SOR_DP_TPG),
1429 DEBUGFS_REG32(SOR_DP_TPG_CONFIG),
1430 DEBUGFS_REG32(SOR_DP_LQ_CSTM0),
1431 DEBUGFS_REG32(SOR_DP_LQ_CSTM1),
1432 DEBUGFS_REG32(SOR_DP_LQ_CSTM2),
1433};
1434
Thierry Redingdab16332015-01-26 16:04:08 +01001435static int tegra_sor_show_regs(struct seq_file *s, void *data)
1436{
1437 struct drm_info_node *node = s->private;
1438 struct tegra_sor *sor = node->info_ent->data;
Thierry Reding850bab42015-07-29 17:58:41 +02001439 struct drm_crtc *crtc = sor->output.encoder.crtc;
1440 struct drm_device *drm = node->minor->dev;
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001441 unsigned int i;
Thierry Reding850bab42015-07-29 17:58:41 +02001442 int err = 0;
1443
1444 drm_modeset_lock_all(drm);
1445
1446 if (!crtc || !crtc->state->active) {
1447 err = -EBUSY;
1448 goto unlock;
1449 }
Thierry Redingdab16332015-01-26 16:04:08 +01001450
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001451 for (i = 0; i < ARRAY_SIZE(tegra_sor_regs); i++) {
1452 unsigned int offset = tegra_sor_regs[i].offset;
Thierry Redingdab16332015-01-26 16:04:08 +01001453
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001454 seq_printf(s, "%-38s %#05x %08x\n", tegra_sor_regs[i].name,
1455 offset, tegra_sor_readl(sor, offset));
1456 }
Thierry Redingdab16332015-01-26 16:04:08 +01001457
Thierry Reding850bab42015-07-29 17:58:41 +02001458unlock:
1459 drm_modeset_unlock_all(drm);
1460 return err;
Thierry Redingdab16332015-01-26 16:04:08 +01001461}
1462
1463static const struct drm_info_list debugfs_files[] = {
Thierry Reding530239a2015-08-06 11:04:54 +02001464 { "crc", tegra_sor_show_crc, 0, NULL },
Thierry Redingdab16332015-01-26 16:04:08 +01001465 { "regs", tegra_sor_show_regs, 0, NULL },
1466};
1467
Thierry Reding5b8e0432017-11-08 13:20:01 +01001468static int tegra_sor_late_register(struct drm_connector *connector)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001469{
Thierry Reding5b8e0432017-11-08 13:20:01 +01001470 struct tegra_output *output = connector_to_output(connector);
1471 unsigned int i, count = ARRAY_SIZE(debugfs_files);
1472 struct drm_minor *minor = connector->dev->primary;
1473 struct dentry *root = connector->debugfs_entry;
1474 struct tegra_sor *sor = to_sor(output);
Thierry Reding530239a2015-08-06 11:04:54 +02001475 int err;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001476
Thierry Redingdab16332015-01-26 16:04:08 +01001477 sor->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1478 GFP_KERNEL);
Thierry Reding5b8e0432017-11-08 13:20:01 +01001479 if (!sor->debugfs_files)
1480 return -ENOMEM;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001481
Thierry Reding5b8e0432017-11-08 13:20:01 +01001482 for (i = 0; i < count; i++)
Thierry Redingdab16332015-01-26 16:04:08 +01001483 sor->debugfs_files[i].data = sor;
1484
Thierry Reding5b8e0432017-11-08 13:20:01 +01001485 err = drm_debugfs_create_files(sor->debugfs_files, count, root, minor);
Thierry Redingdab16332015-01-26 16:04:08 +01001486 if (err < 0)
1487 goto free;
1488
Thierry Reding530239a2015-08-06 11:04:54 +02001489 return 0;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001490
Thierry Redingdab16332015-01-26 16:04:08 +01001491free:
1492 kfree(sor->debugfs_files);
1493 sor->debugfs_files = NULL;
Thierry Reding5b8e0432017-11-08 13:20:01 +01001494
Thierry Reding6fad8f62014-11-28 15:41:34 +01001495 return err;
1496}
1497
Thierry Reding5b8e0432017-11-08 13:20:01 +01001498static void tegra_sor_early_unregister(struct drm_connector *connector)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001499{
Thierry Reding5b8e0432017-11-08 13:20:01 +01001500 struct tegra_output *output = connector_to_output(connector);
1501 unsigned int count = ARRAY_SIZE(debugfs_files);
1502 struct tegra_sor *sor = to_sor(output);
Thierry Redingd92e6002017-10-12 19:07:54 +02001503
Thierry Reding5b8e0432017-11-08 13:20:01 +01001504 drm_debugfs_remove_files(sor->debugfs_files, count,
1505 connector->dev->primary);
Thierry Redingdab16332015-01-26 16:04:08 +01001506 kfree(sor->debugfs_files);
Thierry Reding066d30f2015-07-03 14:16:30 +02001507 sor->debugfs_files = NULL;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001508}
1509
Thierry Redingc31efa72015-09-08 16:09:22 +02001510static void tegra_sor_connector_reset(struct drm_connector *connector)
1511{
1512 struct tegra_sor_state *state;
1513
1514 state = kzalloc(sizeof(*state), GFP_KERNEL);
1515 if (!state)
1516 return;
1517
1518 if (connector->state) {
1519 __drm_atomic_helper_connector_destroy_state(connector->state);
1520 kfree(connector->state);
1521 }
1522
1523 __drm_atomic_helper_connector_reset(connector, &state->base);
1524}
1525
Thierry Reding6fad8f62014-11-28 15:41:34 +01001526static enum drm_connector_status
1527tegra_sor_connector_detect(struct drm_connector *connector, bool force)
1528{
1529 struct tegra_output *output = connector_to_output(connector);
1530 struct tegra_sor *sor = to_sor(output);
1531
Thierry Reding9542c232015-07-08 13:39:09 +02001532 if (sor->aux)
1533 return drm_dp_aux_detect(sor->aux);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001534
Thierry Reding459cc2c2015-07-30 10:34:24 +02001535 return tegra_output_connector_detect(connector, force);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001536}
1537
Thierry Redingc31efa72015-09-08 16:09:22 +02001538static struct drm_connector_state *
1539tegra_sor_connector_duplicate_state(struct drm_connector *connector)
1540{
1541 struct tegra_sor_state *state = to_sor_state(connector->state);
1542 struct tegra_sor_state *copy;
1543
1544 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
1545 if (!copy)
1546 return NULL;
1547
1548 __drm_atomic_helper_connector_duplicate_state(connector, &copy->base);
1549
1550 return &copy->base;
1551}
1552
Thierry Reding6fad8f62014-11-28 15:41:34 +01001553static const struct drm_connector_funcs tegra_sor_connector_funcs = {
Thierry Redingc31efa72015-09-08 16:09:22 +02001554 .reset = tegra_sor_connector_reset,
Thierry Reding6fad8f62014-11-28 15:41:34 +01001555 .detect = tegra_sor_connector_detect,
1556 .fill_modes = drm_helper_probe_single_connector_modes,
1557 .destroy = tegra_output_connector_destroy,
Thierry Redingc31efa72015-09-08 16:09:22 +02001558 .atomic_duplicate_state = tegra_sor_connector_duplicate_state,
Thierry Reding4aa3df72014-11-24 16:27:13 +01001559 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
Thierry Reding5b8e0432017-11-08 13:20:01 +01001560 .late_register = tegra_sor_late_register,
1561 .early_unregister = tegra_sor_early_unregister,
Thierry Reding6fad8f62014-11-28 15:41:34 +01001562};
1563
1564static int tegra_sor_connector_get_modes(struct drm_connector *connector)
1565{
1566 struct tegra_output *output = connector_to_output(connector);
1567 struct tegra_sor *sor = to_sor(output);
1568 int err;
1569
Thierry Reding9542c232015-07-08 13:39:09 +02001570 if (sor->aux)
1571 drm_dp_aux_enable(sor->aux);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001572
1573 err = tegra_output_connector_get_modes(connector);
1574
Thierry Reding9542c232015-07-08 13:39:09 +02001575 if (sor->aux)
1576 drm_dp_aux_disable(sor->aux);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001577
1578 return err;
1579}
1580
1581static enum drm_mode_status
1582tegra_sor_connector_mode_valid(struct drm_connector *connector,
1583 struct drm_display_mode *mode)
1584{
1585 return MODE_OK;
1586}
1587
1588static const struct drm_connector_helper_funcs tegra_sor_connector_helper_funcs = {
1589 .get_modes = tegra_sor_connector_get_modes,
1590 .mode_valid = tegra_sor_connector_mode_valid,
Thierry Reding6fad8f62014-11-28 15:41:34 +01001591};
1592
1593static const struct drm_encoder_funcs tegra_sor_encoder_funcs = {
1594 .destroy = tegra_output_encoder_destroy,
1595};
1596
Thierry Reding850bab42015-07-29 17:58:41 +02001597static void tegra_sor_edp_disable(struct drm_encoder *encoder)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001598{
Thierry Reding850bab42015-07-29 17:58:41 +02001599 struct tegra_output *output = encoder_to_output(encoder);
1600 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
1601 struct tegra_sor *sor = to_sor(output);
1602 u32 value;
1603 int err;
1604
1605 if (output->panel)
1606 drm_panel_disable(output->panel);
1607
1608 err = tegra_sor_detach(sor);
1609 if (err < 0)
1610 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
1611
1612 tegra_sor_writel(sor, 0, SOR_STATE1);
1613 tegra_sor_update(sor);
1614
1615 /*
1616 * The following accesses registers of the display controller, so make
1617 * sure it's only executed when the output is attached to one.
1618 */
1619 if (dc) {
1620 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc57997b2017-10-12 19:12:57 +02001621 value &= ~SOR_ENABLE(0);
Thierry Reding850bab42015-07-29 17:58:41 +02001622 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
1623
1624 tegra_dc_commit(dc);
1625 }
1626
1627 err = tegra_sor_power_down(sor);
1628 if (err < 0)
1629 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
1630
Thierry Reding9542c232015-07-08 13:39:09 +02001631 if (sor->aux) {
1632 err = drm_dp_aux_disable(sor->aux);
Thierry Reding850bab42015-07-29 17:58:41 +02001633 if (err < 0)
1634 dev_err(sor->dev, "failed to disable DP: %d\n", err);
1635 }
1636
Thierry Redingc57997b2017-10-12 19:12:57 +02001637 err = tegra_io_pad_power_disable(sor->pad);
Thierry Reding850bab42015-07-29 17:58:41 +02001638 if (err < 0)
Thierry Redingc57997b2017-10-12 19:12:57 +02001639 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
Thierry Reding850bab42015-07-29 17:58:41 +02001640
1641 if (output->panel)
1642 drm_panel_unprepare(output->panel);
1643
Thierry Redingaaff8bd2015-08-07 16:04:54 +02001644 pm_runtime_put(sor->dev);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001645}
1646
Thierry Reding459cc2c2015-07-30 10:34:24 +02001647#if 0
1648static int calc_h_ref_to_sync(const struct drm_display_mode *mode,
1649 unsigned int *value)
1650{
1651 unsigned int hfp, hsw, hbp, a = 0, b;
1652
1653 hfp = mode->hsync_start - mode->hdisplay;
1654 hsw = mode->hsync_end - mode->hsync_start;
1655 hbp = mode->htotal - mode->hsync_end;
1656
1657 pr_info("hfp: %u, hsw: %u, hbp: %u\n", hfp, hsw, hbp);
1658
1659 b = hfp - 1;
1660
1661 pr_info("a: %u, b: %u\n", a, b);
1662 pr_info("a + hsw + hbp = %u\n", a + hsw + hbp);
1663
1664 if (a + hsw + hbp <= 11) {
1665 a = 1 + 11 - hsw - hbp;
1666 pr_info("a: %u\n", a);
1667 }
1668
1669 if (a > b)
1670 return -EINVAL;
1671
1672 if (hsw < 1)
1673 return -EINVAL;
1674
1675 if (mode->hdisplay < 16)
1676 return -EINVAL;
1677
1678 if (value) {
1679 if (b > a && a % 2)
1680 *value = a + 1;
1681 else
1682 *value = a;
1683 }
1684
1685 return 0;
1686}
1687#endif
1688
Thierry Reding850bab42015-07-29 17:58:41 +02001689static void tegra_sor_edp_enable(struct drm_encoder *encoder)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001690{
Thierry Reding850bab42015-07-29 17:58:41 +02001691 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001692 struct tegra_output *output = encoder_to_output(encoder);
1693 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001694 struct tegra_sor *sor = to_sor(output);
Thierry Reding34fa1832014-06-05 16:31:10 +02001695 struct tegra_sor_config config;
Thierry Redingc31efa72015-09-08 16:09:22 +02001696 struct tegra_sor_state *state;
Thierry Reding34fa1832014-06-05 16:31:10 +02001697 struct drm_dp_link link;
Thierry Reding01b9bea2015-11-11 17:15:29 +01001698 u8 rate, lanes;
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001699 unsigned int i;
Thierry Reding86f5c522014-03-26 11:13:16 +01001700 int err = 0;
Thierry Reding28fe2072015-01-26 16:02:48 +01001701 u32 value;
Thierry Reding86f5c522014-03-26 11:13:16 +01001702
Thierry Redingc31efa72015-09-08 16:09:22 +02001703 state = to_sor_state(output->connector.state);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001704
Thierry Redingaaff8bd2015-08-07 16:04:54 +02001705 pm_runtime_get_sync(sor->dev);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001706
Thierry Reding6fad8f62014-11-28 15:41:34 +01001707 if (output->panel)
1708 drm_panel_prepare(output->panel);
1709
Thierry Reding01b9bea2015-11-11 17:15:29 +01001710 err = drm_dp_aux_enable(sor->aux);
1711 if (err < 0)
1712 dev_err(sor->dev, "failed to enable DP: %d\n", err);
Thierry Reding34fa1832014-06-05 16:31:10 +02001713
Thierry Reding01b9bea2015-11-11 17:15:29 +01001714 err = drm_dp_link_probe(sor->aux, &link);
1715 if (err < 0) {
1716 dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
1717 return;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001718 }
1719
Thierry Reding25bb2ce2015-08-03 14:23:29 +02001720 /* switch to safe parent clock */
1721 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001722 if (err < 0)
1723 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
1724
Thierry Reding34fa1832014-06-05 16:31:10 +02001725 memset(&config, 0, sizeof(config));
Thierry Redingc31efa72015-09-08 16:09:22 +02001726 config.bits_per_pixel = state->bpc * 3;
Thierry Reding34fa1832014-06-05 16:31:10 +02001727
Thierry Redinga1983592015-07-21 16:46:52 +02001728 err = tegra_sor_compute_config(sor, mode, &config, &link);
Thierry Reding34fa1832014-06-05 16:31:10 +02001729 if (err < 0)
Thierry Redinga1983592015-07-21 16:46:52 +02001730 dev_err(sor->dev, "failed to compute configuration: %d\n", err);
Thierry Reding34fa1832014-06-05 16:31:10 +02001731
Thierry Reding6b6b6042013-11-15 16:06:05 +01001732 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1733 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
1734 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
1735 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1736
Thierry Reding880cee02017-10-12 19:04:17 +02001737 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001738 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001739 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001740 usleep_range(20, 100);
1741
Thierry Reding880cee02017-10-12 19:04:17 +02001742 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001743 value |= SOR_PLL3_PLL_VDD_MODE_3V3;
Thierry Reding880cee02017-10-12 19:04:17 +02001744 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001745
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001746 value = SOR_PLL0_ICHPMP(0xf) | SOR_PLL0_VCOCAP_RST |
1747 SOR_PLL0_PLLREG_LEVEL_V45 | SOR_PLL0_RESISTOR_EXT;
Thierry Reding880cee02017-10-12 19:04:17 +02001748 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001749
Thierry Reding880cee02017-10-12 19:04:17 +02001750 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001751 value |= SOR_PLL2_SEQ_PLLCAPPD;
1752 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
1753 value |= SOR_PLL2_LVDS_ENABLE;
Thierry Reding880cee02017-10-12 19:04:17 +02001754 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001755
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001756 value = SOR_PLL1_TERM_COMPOUT | SOR_PLL1_TMDS_TERM;
Thierry Reding880cee02017-10-12 19:04:17 +02001757 tegra_sor_writel(sor, value, sor->soc->regs->pll1);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001758
1759 while (true) {
Thierry Reding880cee02017-10-12 19:04:17 +02001760 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001761 if ((value & SOR_PLL2_SEQ_PLLCAPPD_ENFORCE) == 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001762 break;
1763
1764 usleep_range(250, 1000);
1765 }
1766
Thierry Reding880cee02017-10-12 19:04:17 +02001767 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001768 value &= ~SOR_PLL2_POWERDOWN_OVERRIDE;
1769 value &= ~SOR_PLL2_PORT_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001770 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001771
1772 /*
1773 * power up
1774 */
1775
1776 /* set safe link bandwidth (1.62 Gbps) */
1777 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1778 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
1779 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62;
1780 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1781
1782 /* step 1 */
Thierry Reding880cee02017-10-12 19:04:17 +02001783 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001784 value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL2_PORT_POWERDOWN |
1785 SOR_PLL2_BANDGAP_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001786 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001787
Thierry Reding880cee02017-10-12 19:04:17 +02001788 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001789 value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
Thierry Reding880cee02017-10-12 19:04:17 +02001790 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001791
Thierry Reding880cee02017-10-12 19:04:17 +02001792 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001793 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
Thierry Reding880cee02017-10-12 19:04:17 +02001794 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001795
1796 /* step 2 */
Thierry Redingc57997b2017-10-12 19:12:57 +02001797 err = tegra_io_pad_power_enable(sor->pad);
Thierry Reding850bab42015-07-29 17:58:41 +02001798 if (err < 0)
Thierry Redingc57997b2017-10-12 19:12:57 +02001799 dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001800
1801 usleep_range(5, 100);
1802
1803 /* step 3 */
Thierry Reding880cee02017-10-12 19:04:17 +02001804 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001805 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001806 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001807
1808 usleep_range(20, 100);
1809
1810 /* step 4 */
Thierry Reding880cee02017-10-12 19:04:17 +02001811 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001812 value &= ~SOR_PLL0_VCOPD;
1813 value &= ~SOR_PLL0_PWR;
Thierry Reding880cee02017-10-12 19:04:17 +02001814 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001815
Thierry Reding880cee02017-10-12 19:04:17 +02001816 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001817 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
Thierry Reding880cee02017-10-12 19:04:17 +02001818 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001819
1820 usleep_range(200, 1000);
1821
1822 /* step 5 */
Thierry Reding880cee02017-10-12 19:04:17 +02001823 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001824 value &= ~SOR_PLL2_PORT_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001825 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001826
Thierry Reding30b49432015-08-03 15:50:32 +02001827 /* XXX not in TRM */
1828 for (value = 0, i = 0; i < 5; i++)
1829 value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->soc->xbar_cfg[i]) |
1830 SOR_XBAR_CTRL_LINK1_XSEL(i, i);
1831
1832 tegra_sor_writel(sor, 0x00000000, SOR_XBAR_POL);
1833 tegra_sor_writel(sor, value, SOR_XBAR_CTRL);
1834
Thierry Reding25bb2ce2015-08-03 14:23:29 +02001835 /* switch to DP parent clock */
1836 err = tegra_sor_set_parent_clock(sor, sor->clk_dp);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001837 if (err < 0)
Thierry Reding25bb2ce2015-08-03 14:23:29 +02001838 dev_err(sor->dev, "failed to set parent clock: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001839
Thierry Reding899451b2014-06-05 16:19:48 +02001840 /* power DP lanes */
Thierry Reding880cee02017-10-12 19:04:17 +02001841 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding899451b2014-06-05 16:19:48 +02001842
1843 if (link.num_lanes <= 2)
1844 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2);
1845 else
1846 value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2;
1847
1848 if (link.num_lanes <= 1)
1849 value &= ~SOR_DP_PADCTL_PD_TXD_1;
1850 else
1851 value |= SOR_DP_PADCTL_PD_TXD_1;
1852
1853 if (link.num_lanes == 0)
1854 value &= ~SOR_DP_PADCTL_PD_TXD_0;
1855 else
1856 value |= SOR_DP_PADCTL_PD_TXD_0;
1857
Thierry Reding880cee02017-10-12 19:04:17 +02001858 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001859
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001860 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001861 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
Thierry Reding0c90a182014-06-05 16:29:46 +02001862 value |= SOR_DP_LINKCTL_LANE_COUNT(link.num_lanes);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001863 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001864
1865 /* start lane sequencer */
1866 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
1867 SOR_LANE_SEQ_CTL_POWER_STATE_UP;
1868 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
1869
1870 while (true) {
1871 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
1872 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
1873 break;
1874
1875 usleep_range(250, 1000);
1876 }
1877
Thierry Redinga4263fe2014-06-05 16:16:23 +02001878 /* set link bandwidth */
Thierry Reding6b6b6042013-11-15 16:06:05 +01001879 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1880 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
Thierry Redinga4263fe2014-06-05 16:16:23 +02001881 value |= drm_dp_link_rate_to_bw_code(link.rate) << 2;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001882 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1883
Thierry Reding402f6bc2015-07-21 16:48:19 +02001884 tegra_sor_apply_config(sor, &config);
1885
1886 /* enable link */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001887 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001888 value |= SOR_DP_LINKCTL_ENABLE;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001889 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001890 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001891
1892 for (i = 0, value = 0; i < 4; i++) {
1893 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
1894 SOR_DP_TPG_SCRAMBLER_GALIOS |
1895 SOR_DP_TPG_PATTERN_NONE;
1896 value = (value << 8) | lane;
1897 }
1898
1899 tegra_sor_writel(sor, value, SOR_DP_TPG);
1900
Thierry Reding6b6b6042013-11-15 16:06:05 +01001901 /* enable pad calibration logic */
Thierry Reding880cee02017-10-12 19:04:17 +02001902 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001903 value |= SOR_DP_PADCTL_PAD_CAL_PD;
Thierry Reding880cee02017-10-12 19:04:17 +02001904 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001905
Thierry Reding01b9bea2015-11-11 17:15:29 +01001906 err = drm_dp_link_probe(sor->aux, &link);
1907 if (err < 0)
1908 dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001909
Thierry Reding01b9bea2015-11-11 17:15:29 +01001910 err = drm_dp_link_power_up(sor->aux, &link);
1911 if (err < 0)
1912 dev_err(sor->dev, "failed to power up eDP link: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001913
Thierry Reding01b9bea2015-11-11 17:15:29 +01001914 err = drm_dp_link_configure(sor->aux, &link);
1915 if (err < 0)
1916 dev_err(sor->dev, "failed to configure eDP link: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001917
Thierry Reding01b9bea2015-11-11 17:15:29 +01001918 rate = drm_dp_link_rate_to_bw_code(link.rate);
1919 lanes = link.num_lanes;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001920
Thierry Reding01b9bea2015-11-11 17:15:29 +01001921 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1922 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
1923 value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
1924 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001925
Thierry Reding01b9bea2015-11-11 17:15:29 +01001926 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
1927 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
1928 value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001929
Thierry Reding01b9bea2015-11-11 17:15:29 +01001930 if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
1931 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001932
Thierry Reding01b9bea2015-11-11 17:15:29 +01001933 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001934
Thierry Reding01b9bea2015-11-11 17:15:29 +01001935 /* disable training pattern generator */
Thierry Reding6b6b6042013-11-15 16:06:05 +01001936
Thierry Reding01b9bea2015-11-11 17:15:29 +01001937 for (i = 0; i < link.num_lanes; i++) {
1938 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
1939 SOR_DP_TPG_SCRAMBLER_GALIOS |
1940 SOR_DP_TPG_PATTERN_NONE;
1941 value = (value << 8) | lane;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001942 }
1943
Thierry Reding01b9bea2015-11-11 17:15:29 +01001944 tegra_sor_writel(sor, value, SOR_DP_TPG);
1945
1946 err = tegra_sor_dp_train_fast(sor, &link);
1947 if (err < 0)
1948 dev_err(sor->dev, "DP fast link training failed: %d\n", err);
1949
1950 dev_dbg(sor->dev, "fast link training succeeded\n");
1951
Thierry Reding6b6b6042013-11-15 16:06:05 +01001952 err = tegra_sor_power_up(sor, 250);
Thierry Reding850bab42015-07-29 17:58:41 +02001953 if (err < 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001954 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001955
Thierry Reding6b6b6042013-11-15 16:06:05 +01001956 /* CSTM (LVDS, link A/B, upper) */
Stéphane Marchesin143b1df2014-05-22 20:32:47 -07001957 value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B |
Thierry Reding6b6b6042013-11-15 16:06:05 +01001958 SOR_CSTM_UPPER;
1959 tegra_sor_writel(sor, value, SOR_CSTM);
1960
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001961 /* use DP-A protocol */
1962 value = tegra_sor_readl(sor, SOR_STATE1);
1963 value &= ~SOR_STATE_ASY_PROTOCOL_MASK;
1964 value |= SOR_STATE_ASY_PROTOCOL_DP_A;
1965 tegra_sor_writel(sor, value, SOR_STATE1);
1966
Thierry Redingc31efa72015-09-08 16:09:22 +02001967 tegra_sor_mode_set(sor, mode, state);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001968
Thierry Reding6b6b6042013-11-15 16:06:05 +01001969 /* PWM setup */
1970 err = tegra_sor_setup_pwm(sor, 250);
Thierry Reding850bab42015-07-29 17:58:41 +02001971 if (err < 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001972 dev_err(sor->dev, "failed to setup PWM: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001973
Thierry Reding666cb872014-12-08 16:32:47 +01001974 tegra_sor_update(sor);
1975
Thierry Reding6b6b6042013-11-15 16:06:05 +01001976 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc57997b2017-10-12 19:12:57 +02001977 value |= SOR_ENABLE(0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001978 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
1979
Thierry Reding666cb872014-12-08 16:32:47 +01001980 tegra_dc_commit(dc);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001981
1982 err = tegra_sor_attach(sor);
Thierry Reding850bab42015-07-29 17:58:41 +02001983 if (err < 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001984 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001985
1986 err = tegra_sor_wakeup(sor);
Thierry Reding850bab42015-07-29 17:58:41 +02001987 if (err < 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001988 dev_err(sor->dev, "failed to enable DC: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001989
Thierry Reding6fad8f62014-11-28 15:41:34 +01001990 if (output->panel)
1991 drm_panel_enable(output->panel);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001992}
1993
Thierry Reding82f15112014-12-08 17:26:46 +01001994static int
1995tegra_sor_encoder_atomic_check(struct drm_encoder *encoder,
1996 struct drm_crtc_state *crtc_state,
1997 struct drm_connector_state *conn_state)
1998{
1999 struct tegra_output *output = encoder_to_output(encoder);
Thierry Redingc31efa72015-09-08 16:09:22 +02002000 struct tegra_sor_state *state = to_sor_state(conn_state);
Thierry Reding82f15112014-12-08 17:26:46 +01002001 struct tegra_dc *dc = to_tegra_dc(conn_state->crtc);
2002 unsigned long pclk = crtc_state->mode.clock * 1000;
2003 struct tegra_sor *sor = to_sor(output);
Thierry Redingc31efa72015-09-08 16:09:22 +02002004 struct drm_display_info *info;
Thierry Reding82f15112014-12-08 17:26:46 +01002005 int err;
2006
Thierry Redingc31efa72015-09-08 16:09:22 +02002007 info = &output->connector.display_info;
2008
Thierry Reding36e90222017-10-12 19:14:21 +02002009 /*
2010 * For HBR2 modes, the SOR brick needs to use the x20 multiplier, so
2011 * the pixel clock must be corrected accordingly.
2012 */
2013 if (pclk >= 340000000) {
2014 state->link_speed = 20;
2015 state->pclk = pclk / 2;
2016 } else {
2017 state->link_speed = 10;
2018 state->pclk = pclk;
2019 }
2020
Thierry Reding82f15112014-12-08 17:26:46 +01002021 err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent,
2022 pclk, 0);
2023 if (err < 0) {
2024 dev_err(output->dev, "failed to setup CRTC state: %d\n", err);
2025 return err;
2026 }
2027
Thierry Redingc31efa72015-09-08 16:09:22 +02002028 switch (info->bpc) {
2029 case 8:
2030 case 6:
2031 state->bpc = info->bpc;
2032 break;
2033
2034 default:
2035 DRM_DEBUG_KMS("%u bits-per-color not supported\n", info->bpc);
2036 state->bpc = 8;
2037 break;
2038 }
2039
Thierry Reding82f15112014-12-08 17:26:46 +01002040 return 0;
2041}
2042
Thierry Reding459cc2c2015-07-30 10:34:24 +02002043static const struct drm_encoder_helper_funcs tegra_sor_edp_helpers = {
Thierry Reding850bab42015-07-29 17:58:41 +02002044 .disable = tegra_sor_edp_disable,
2045 .enable = tegra_sor_edp_enable,
Thierry Reding82f15112014-12-08 17:26:46 +01002046 .atomic_check = tegra_sor_encoder_atomic_check,
Thierry Reding6b6b6042013-11-15 16:06:05 +01002047};
2048
Thierry Reding459cc2c2015-07-30 10:34:24 +02002049static inline u32 tegra_sor_hdmi_subpack(const u8 *ptr, size_t size)
2050{
2051 u32 value = 0;
2052 size_t i;
2053
2054 for (i = size; i > 0; i--)
2055 value = (value << 8) | ptr[i - 1];
2056
2057 return value;
2058}
2059
2060static void tegra_sor_hdmi_write_infopack(struct tegra_sor *sor,
2061 const void *data, size_t size)
2062{
2063 const u8 *ptr = data;
2064 unsigned long offset;
2065 size_t i, j;
2066 u32 value;
2067
2068 switch (ptr[0]) {
2069 case HDMI_INFOFRAME_TYPE_AVI:
2070 offset = SOR_HDMI_AVI_INFOFRAME_HEADER;
2071 break;
2072
2073 case HDMI_INFOFRAME_TYPE_AUDIO:
2074 offset = SOR_HDMI_AUDIO_INFOFRAME_HEADER;
2075 break;
2076
2077 case HDMI_INFOFRAME_TYPE_VENDOR:
2078 offset = SOR_HDMI_VSI_INFOFRAME_HEADER;
2079 break;
2080
2081 default:
2082 dev_err(sor->dev, "unsupported infoframe type: %02x\n",
2083 ptr[0]);
2084 return;
2085 }
2086
2087 value = INFOFRAME_HEADER_TYPE(ptr[0]) |
2088 INFOFRAME_HEADER_VERSION(ptr[1]) |
2089 INFOFRAME_HEADER_LEN(ptr[2]);
2090 tegra_sor_writel(sor, value, offset);
2091 offset++;
2092
2093 /*
2094 * Each subpack contains 7 bytes, divided into:
2095 * - subpack_low: bytes 0 - 3
2096 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
2097 */
2098 for (i = 3, j = 0; i < size; i += 7, j += 8) {
2099 size_t rem = size - i, num = min_t(size_t, rem, 4);
2100
2101 value = tegra_sor_hdmi_subpack(&ptr[i], num);
2102 tegra_sor_writel(sor, value, offset++);
2103
2104 num = min_t(size_t, rem - num, 3);
2105
2106 value = tegra_sor_hdmi_subpack(&ptr[i + 4], num);
2107 tegra_sor_writel(sor, value, offset++);
2108 }
2109}
2110
2111static int
2112tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
2113 const struct drm_display_mode *mode)
2114{
2115 u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
2116 struct hdmi_avi_infoframe frame;
2117 u32 value;
2118 int err;
2119
2120 /* disable AVI infoframe */
2121 value = tegra_sor_readl(sor, SOR_HDMI_AVI_INFOFRAME_CTRL);
2122 value &= ~INFOFRAME_CTRL_SINGLE;
2123 value &= ~INFOFRAME_CTRL_OTHER;
2124 value &= ~INFOFRAME_CTRL_ENABLE;
2125 tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
2126
Shashank Sharma0c1f5282017-07-13 21:03:07 +05302127 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002128 if (err < 0) {
2129 dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
2130 return err;
2131 }
2132
2133 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
2134 if (err < 0) {
2135 dev_err(sor->dev, "failed to pack AVI infoframe: %d\n", err);
2136 return err;
2137 }
2138
2139 tegra_sor_hdmi_write_infopack(sor, buffer, err);
2140
2141 /* enable AVI infoframe */
2142 value = tegra_sor_readl(sor, SOR_HDMI_AVI_INFOFRAME_CTRL);
2143 value |= INFOFRAME_CTRL_CHECKSUM_ENABLE;
2144 value |= INFOFRAME_CTRL_ENABLE;
2145 tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
2146
2147 return 0;
2148}
2149
Thierry Reding8e2988a72018-12-03 15:46:03 +01002150static void tegra_sor_write_eld(struct tegra_sor *sor)
2151{
2152 size_t length = drm_eld_size(sor->output.connector.eld), i;
2153
2154 for (i = 0; i < length; i++)
2155 tegra_sor_writel(sor, i << 8 | sor->output.connector.eld[i],
2156 SOR_AUDIO_HDA_ELD_BUFWR);
2157
2158 /*
2159 * The HDA codec will always report an ELD buffer size of 96 bytes and
2160 * the HDA codec driver will check that each byte read from the buffer
2161 * is valid. Therefore every byte must be written, even if no 96 bytes
2162 * were parsed from EDID.
2163 */
2164 for (i = length; i < 96; i++)
2165 tegra_sor_writel(sor, i << 8 | 0, SOR_AUDIO_HDA_ELD_BUFWR);
2166}
2167
2168static void tegra_sor_audio_prepare(struct tegra_sor *sor)
2169{
2170 u32 value;
2171
2172 tegra_sor_write_eld(sor);
2173
2174 value = SOR_AUDIO_HDA_PRESENSE_ELDV | SOR_AUDIO_HDA_PRESENSE_PD;
2175 tegra_sor_writel(sor, value, SOR_AUDIO_HDA_PRESENSE);
2176}
2177
2178static void tegra_sor_audio_unprepare(struct tegra_sor *sor)
2179{
2180 tegra_sor_writel(sor, 0, SOR_AUDIO_HDA_PRESENSE);
2181}
2182
2183static int tegra_sor_hdmi_enable_audio_infoframe(struct tegra_sor *sor)
2184{
2185 u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
2186 struct hdmi_audio_infoframe frame;
2187 u32 value;
2188 int err;
2189
2190 err = hdmi_audio_infoframe_init(&frame);
2191 if (err < 0) {
2192 dev_err(sor->dev, "failed to setup audio infoframe: %d\n", err);
2193 return err;
2194 }
2195
2196 frame.channels = sor->audio.channels;
2197
2198 err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
2199 if (err < 0) {
2200 dev_err(sor->dev, "failed to pack audio infoframe: %d\n", err);
2201 return err;
2202 }
2203
2204 tegra_sor_hdmi_write_infopack(sor, buffer, err);
2205
2206 value = tegra_sor_readl(sor, SOR_HDMI_AUDIO_INFOFRAME_CTRL);
2207 value |= INFOFRAME_CTRL_CHECKSUM_ENABLE;
2208 value |= INFOFRAME_CTRL_ENABLE;
2209 tegra_sor_writel(sor, value, SOR_HDMI_AUDIO_INFOFRAME_CTRL);
2210
2211 return 0;
2212}
2213
2214static void tegra_sor_hdmi_audio_enable(struct tegra_sor *sor)
2215{
2216 u32 value;
2217
2218 value = tegra_sor_readl(sor, SOR_AUDIO_CNTRL);
2219
2220 /* select HDA audio input */
2221 value &= ~SOR_AUDIO_CNTRL_SOURCE_SELECT(SOURCE_SELECT_MASK);
2222 value |= SOR_AUDIO_CNTRL_SOURCE_SELECT(SOURCE_SELECT_HDA);
2223
2224 /* inject null samples */
2225 if (sor->audio.channels != 2)
2226 value &= ~SOR_AUDIO_CNTRL_INJECT_NULLSMPL;
2227 else
2228 value |= SOR_AUDIO_CNTRL_INJECT_NULLSMPL;
2229
2230 value |= SOR_AUDIO_CNTRL_AFIFO_FLUSH;
2231
2232 tegra_sor_writel(sor, value, SOR_AUDIO_CNTRL);
2233
2234 /* enable advertising HBR capability */
2235 tegra_sor_writel(sor, SOR_AUDIO_SPARE_HBR_ENABLE, SOR_AUDIO_SPARE);
2236
2237 tegra_sor_writel(sor, 0, SOR_HDMI_ACR_CTRL);
2238
2239 value = SOR_HDMI_SPARE_ACR_PRIORITY_HIGH |
2240 SOR_HDMI_SPARE_CTS_RESET(1) |
2241 SOR_HDMI_SPARE_HW_CTS_ENABLE;
2242 tegra_sor_writel(sor, value, SOR_HDMI_SPARE);
2243
2244 /* enable HW CTS */
2245 value = SOR_HDMI_ACR_SUBPACK_LOW_SB1(0);
2246 tegra_sor_writel(sor, value, SOR_HDMI_ACR_0441_SUBPACK_LOW);
2247
2248 /* allow packet to be sent */
2249 value = SOR_HDMI_ACR_SUBPACK_HIGH_ENABLE;
2250 tegra_sor_writel(sor, value, SOR_HDMI_ACR_0441_SUBPACK_HIGH);
2251
2252 /* reset N counter and enable lookup */
2253 value = SOR_HDMI_AUDIO_N_RESET | SOR_HDMI_AUDIO_N_LOOKUP;
2254 tegra_sor_writel(sor, value, SOR_HDMI_AUDIO_N);
2255
2256 value = (24000 * 4096) / (128 * sor->audio.sample_rate / 1000);
2257 tegra_sor_writel(sor, value, SOR_AUDIO_AVAL_0320);
2258 tegra_sor_writel(sor, 4096, SOR_AUDIO_NVAL_0320);
2259
2260 tegra_sor_writel(sor, 20000, SOR_AUDIO_AVAL_0441);
2261 tegra_sor_writel(sor, 4704, SOR_AUDIO_NVAL_0441);
2262
2263 tegra_sor_writel(sor, 20000, SOR_AUDIO_AVAL_0882);
2264 tegra_sor_writel(sor, 9408, SOR_AUDIO_NVAL_0882);
2265
2266 tegra_sor_writel(sor, 20000, SOR_AUDIO_AVAL_1764);
2267 tegra_sor_writel(sor, 18816, SOR_AUDIO_NVAL_1764);
2268
2269 value = (24000 * 6144) / (128 * sor->audio.sample_rate / 1000);
2270 tegra_sor_writel(sor, value, SOR_AUDIO_AVAL_0480);
2271 tegra_sor_writel(sor, 6144, SOR_AUDIO_NVAL_0480);
2272
2273 value = (24000 * 12288) / (128 * sor->audio.sample_rate / 1000);
2274 tegra_sor_writel(sor, value, SOR_AUDIO_AVAL_0960);
2275 tegra_sor_writel(sor, 12288, SOR_AUDIO_NVAL_0960);
2276
2277 value = (24000 * 24576) / (128 * sor->audio.sample_rate / 1000);
2278 tegra_sor_writel(sor, value, SOR_AUDIO_AVAL_1920);
2279 tegra_sor_writel(sor, 24576, SOR_AUDIO_NVAL_1920);
2280
2281 value = tegra_sor_readl(sor, SOR_HDMI_AUDIO_N);
2282 value &= ~SOR_HDMI_AUDIO_N_RESET;
2283 tegra_sor_writel(sor, value, SOR_HDMI_AUDIO_N);
2284
2285 tegra_sor_hdmi_enable_audio_infoframe(sor);
2286}
2287
Thierry Reding459cc2c2015-07-30 10:34:24 +02002288static void tegra_sor_hdmi_disable_audio_infoframe(struct tegra_sor *sor)
2289{
2290 u32 value;
2291
2292 value = tegra_sor_readl(sor, SOR_HDMI_AUDIO_INFOFRAME_CTRL);
2293 value &= ~INFOFRAME_CTRL_ENABLE;
2294 tegra_sor_writel(sor, value, SOR_HDMI_AUDIO_INFOFRAME_CTRL);
2295}
2296
Thierry Reding8e2988a72018-12-03 15:46:03 +01002297static void tegra_sor_hdmi_audio_disable(struct tegra_sor *sor)
2298{
2299 tegra_sor_hdmi_disable_audio_infoframe(sor);
2300}
2301
Thierry Reding459cc2c2015-07-30 10:34:24 +02002302static struct tegra_sor_hdmi_settings *
2303tegra_sor_hdmi_find_settings(struct tegra_sor *sor, unsigned long frequency)
2304{
2305 unsigned int i;
2306
2307 for (i = 0; i < sor->num_settings; i++)
2308 if (frequency <= sor->settings[i].frequency)
2309 return &sor->settings[i];
2310
2311 return NULL;
2312}
2313
Thierry Reding36e90222017-10-12 19:14:21 +02002314static void tegra_sor_hdmi_disable_scrambling(struct tegra_sor *sor)
2315{
2316 u32 value;
2317
2318 value = tegra_sor_readl(sor, SOR_HDMI2_CTRL);
2319 value &= ~SOR_HDMI2_CTRL_CLOCK_MODE_DIV_BY_4;
2320 value &= ~SOR_HDMI2_CTRL_SCRAMBLE;
2321 tegra_sor_writel(sor, value, SOR_HDMI2_CTRL);
2322}
2323
2324static void tegra_sor_hdmi_scdc_disable(struct tegra_sor *sor)
2325{
2326 struct i2c_adapter *ddc = sor->output.ddc;
2327
2328 drm_scdc_set_high_tmds_clock_ratio(ddc, false);
2329 drm_scdc_set_scrambling(ddc, false);
2330
2331 tegra_sor_hdmi_disable_scrambling(sor);
2332}
2333
2334static void tegra_sor_hdmi_scdc_stop(struct tegra_sor *sor)
2335{
2336 if (sor->scdc_enabled) {
2337 cancel_delayed_work_sync(&sor->scdc);
2338 tegra_sor_hdmi_scdc_disable(sor);
2339 }
2340}
2341
2342static void tegra_sor_hdmi_enable_scrambling(struct tegra_sor *sor)
2343{
2344 u32 value;
2345
2346 value = tegra_sor_readl(sor, SOR_HDMI2_CTRL);
2347 value |= SOR_HDMI2_CTRL_CLOCK_MODE_DIV_BY_4;
2348 value |= SOR_HDMI2_CTRL_SCRAMBLE;
2349 tegra_sor_writel(sor, value, SOR_HDMI2_CTRL);
2350}
2351
2352static void tegra_sor_hdmi_scdc_enable(struct tegra_sor *sor)
2353{
2354 struct i2c_adapter *ddc = sor->output.ddc;
2355
2356 drm_scdc_set_high_tmds_clock_ratio(ddc, true);
2357 drm_scdc_set_scrambling(ddc, true);
2358
2359 tegra_sor_hdmi_enable_scrambling(sor);
2360}
2361
2362static void tegra_sor_hdmi_scdc_work(struct work_struct *work)
2363{
2364 struct tegra_sor *sor = container_of(work, struct tegra_sor, scdc.work);
2365 struct i2c_adapter *ddc = sor->output.ddc;
2366
2367 if (!drm_scdc_get_scrambling_status(ddc)) {
2368 DRM_DEBUG_KMS("SCDC not scrambled\n");
2369 tegra_sor_hdmi_scdc_enable(sor);
2370 }
2371
2372 schedule_delayed_work(&sor->scdc, msecs_to_jiffies(5000));
2373}
2374
2375static void tegra_sor_hdmi_scdc_start(struct tegra_sor *sor)
2376{
2377 struct drm_scdc *scdc = &sor->output.connector.display_info.hdmi.scdc;
2378 struct drm_display_mode *mode;
2379
2380 mode = &sor->output.encoder.crtc->state->adjusted_mode;
2381
2382 if (mode->clock >= 340000 && scdc->supported) {
2383 schedule_delayed_work(&sor->scdc, msecs_to_jiffies(5000));
2384 tegra_sor_hdmi_scdc_enable(sor);
2385 sor->scdc_enabled = true;
2386 }
2387}
2388
Thierry Reding459cc2c2015-07-30 10:34:24 +02002389static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
2390{
2391 struct tegra_output *output = encoder_to_output(encoder);
2392 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
2393 struct tegra_sor *sor = to_sor(output);
2394 u32 value;
2395 int err;
2396
Thierry Reding8e2988a72018-12-03 15:46:03 +01002397 tegra_sor_audio_unprepare(sor);
Thierry Reding36e90222017-10-12 19:14:21 +02002398 tegra_sor_hdmi_scdc_stop(sor);
2399
Thierry Reding459cc2c2015-07-30 10:34:24 +02002400 err = tegra_sor_detach(sor);
2401 if (err < 0)
2402 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
2403
2404 tegra_sor_writel(sor, 0, SOR_STATE1);
2405 tegra_sor_update(sor);
2406
2407 /* disable display to SOR clock */
2408 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc57997b2017-10-12 19:12:57 +02002409
2410 if (!sor->soc->has_nvdisplay)
2411 value &= ~(SOR1_TIMING_CYA | SOR_ENABLE(1));
2412 else
2413 value &= ~SOR_ENABLE(sor->index);
2414
Thierry Reding459cc2c2015-07-30 10:34:24 +02002415 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
2416
2417 tegra_dc_commit(dc);
2418
2419 err = tegra_sor_power_down(sor);
2420 if (err < 0)
2421 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
2422
Thierry Redingc57997b2017-10-12 19:12:57 +02002423 err = tegra_io_pad_power_disable(sor->pad);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002424 if (err < 0)
Thierry Redingc57997b2017-10-12 19:12:57 +02002425 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002426
Thierry Redingaaff8bd2015-08-07 16:04:54 +02002427 pm_runtime_put(sor->dev);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002428}
2429
2430static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2431{
2432 struct tegra_output *output = encoder_to_output(encoder);
2433 unsigned int h_ref_to_sync = 1, pulse_start, max_ac;
2434 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002435 struct tegra_sor_hdmi_settings *settings;
2436 struct tegra_sor *sor = to_sor(output);
Thierry Redingc31efa72015-09-08 16:09:22 +02002437 struct tegra_sor_state *state;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002438 struct drm_display_mode *mode;
Thierry Reding36e90222017-10-12 19:14:21 +02002439 unsigned long rate, pclk;
Thierry Reding30b49432015-08-03 15:50:32 +02002440 unsigned int div, i;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002441 u32 value;
2442 int err;
2443
Thierry Redingc31efa72015-09-08 16:09:22 +02002444 state = to_sor_state(output->connector.state);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002445 mode = &encoder->crtc->state->adjusted_mode;
Thierry Reding36e90222017-10-12 19:14:21 +02002446 pclk = mode->clock * 1000;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002447
Thierry Redingaaff8bd2015-08-07 16:04:54 +02002448 pm_runtime_get_sync(sor->dev);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002449
Thierry Reding25bb2ce2015-08-03 14:23:29 +02002450 /* switch to safe parent clock */
2451 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
Thierry Redinge1335e22017-10-12 17:53:11 +02002452 if (err < 0) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002453 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
Thierry Redinge1335e22017-10-12 17:53:11 +02002454 return;
2455 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002456
2457 div = clk_get_rate(sor->clk) / 1000000 * 4;
2458
Thierry Redingc57997b2017-10-12 19:12:57 +02002459 err = tegra_io_pad_power_enable(sor->pad);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002460 if (err < 0)
Thierry Redingc57997b2017-10-12 19:12:57 +02002461 dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002462
2463 usleep_range(20, 100);
2464
Thierry Reding880cee02017-10-12 19:04:17 +02002465 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002466 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02002467 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002468
2469 usleep_range(20, 100);
2470
Thierry Reding880cee02017-10-12 19:04:17 +02002471 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002472 value &= ~SOR_PLL3_PLL_VDD_MODE_3V3;
Thierry Reding880cee02017-10-12 19:04:17 +02002473 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002474
Thierry Reding880cee02017-10-12 19:04:17 +02002475 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002476 value &= ~SOR_PLL0_VCOPD;
2477 value &= ~SOR_PLL0_PWR;
Thierry Reding880cee02017-10-12 19:04:17 +02002478 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002479
Thierry Reding880cee02017-10-12 19:04:17 +02002480 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002481 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
Thierry Reding880cee02017-10-12 19:04:17 +02002482 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002483
2484 usleep_range(200, 400);
2485
Thierry Reding880cee02017-10-12 19:04:17 +02002486 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002487 value &= ~SOR_PLL2_POWERDOWN_OVERRIDE;
2488 value &= ~SOR_PLL2_PORT_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02002489 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002490
2491 usleep_range(20, 100);
2492
Thierry Reding880cee02017-10-12 19:04:17 +02002493 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002494 value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
2495 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2;
Thierry Reding880cee02017-10-12 19:04:17 +02002496 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002497
2498 while (true) {
2499 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
2500 if ((value & SOR_LANE_SEQ_CTL_STATE_BUSY) == 0)
2501 break;
2502
2503 usleep_range(250, 1000);
2504 }
2505
2506 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
2507 SOR_LANE_SEQ_CTL_POWER_STATE_UP | SOR_LANE_SEQ_CTL_DELAY(5);
2508 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
2509
2510 while (true) {
2511 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
2512 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
2513 break;
2514
2515 usleep_range(250, 1000);
2516 }
2517
2518 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
2519 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
2520 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
2521
Thierry Reding36e90222017-10-12 19:14:21 +02002522 if (mode->clock < 340000) {
2523 DRM_DEBUG_KMS("setting 2.7 GHz link speed\n");
Thierry Reding459cc2c2015-07-30 10:34:24 +02002524 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70;
Thierry Reding36e90222017-10-12 19:14:21 +02002525 } else {
2526 DRM_DEBUG_KMS("setting 5.4 GHz link speed\n");
Thierry Reding459cc2c2015-07-30 10:34:24 +02002527 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40;
Thierry Reding36e90222017-10-12 19:14:21 +02002528 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002529
2530 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK;
2531 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
2532
Thierry Redingc57997b2017-10-12 19:12:57 +02002533 /* SOR pad PLL stabilization time */
2534 usleep_range(250, 1000);
2535
2536 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
2537 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
2538 value |= SOR_DP_LINKCTL_LANE_COUNT(4);
2539 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
2540
Thierry Reding459cc2c2015-07-30 10:34:24 +02002541 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
Thierry Redingc57997b2017-10-12 19:12:57 +02002542 value &= ~SOR_DP_SPARE_DISP_VIDEO_PREAMBLE;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002543 value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
Thierry Redingc57997b2017-10-12 19:12:57 +02002544 value &= ~SOR_DP_SPARE_SEQ_ENABLE;
2545 value &= ~SOR_DP_SPARE_MACRO_SOR_CLK;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002546 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
2547
2548 value = SOR_SEQ_CTL_PU_PC(0) | SOR_SEQ_CTL_PU_PC_ALT(0) |
2549 SOR_SEQ_CTL_PD_PC(8) | SOR_SEQ_CTL_PD_PC_ALT(8);
2550 tegra_sor_writel(sor, value, SOR_SEQ_CTL);
2551
2552 value = SOR_SEQ_INST_DRIVE_PWM_OUT_LO | SOR_SEQ_INST_HALT |
2553 SOR_SEQ_INST_WAIT_VSYNC | SOR_SEQ_INST_WAIT(1);
2554 tegra_sor_writel(sor, value, SOR_SEQ_INST(0));
2555 tegra_sor_writel(sor, value, SOR_SEQ_INST(8));
2556
Thierry Redingc57997b2017-10-12 19:12:57 +02002557 if (!sor->soc->has_nvdisplay) {
2558 /* program the reference clock */
2559 value = SOR_REFCLK_DIV_INT(div) | SOR_REFCLK_DIV_FRAC(div);
2560 tegra_sor_writel(sor, value, SOR_REFCLK);
2561 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002562
Thierry Reding30b49432015-08-03 15:50:32 +02002563 /* XXX not in TRM */
2564 for (value = 0, i = 0; i < 5; i++)
2565 value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->soc->xbar_cfg[i]) |
2566 SOR_XBAR_CTRL_LINK1_XSEL(i, i);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002567
2568 tegra_sor_writel(sor, 0x00000000, SOR_XBAR_POL);
Thierry Reding30b49432015-08-03 15:50:32 +02002569 tegra_sor_writel(sor, value, SOR_XBAR_CTRL);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002570
Thierry Reding25bb2ce2015-08-03 14:23:29 +02002571 /* switch to parent clock */
Thierry Redinge1335e22017-10-12 17:53:11 +02002572 err = clk_set_parent(sor->clk, sor->clk_parent);
2573 if (err < 0) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002574 dev_err(sor->dev, "failed to set parent clock: %d\n", err);
Thierry Redinge1335e22017-10-12 17:53:11 +02002575 return;
2576 }
2577
2578 err = tegra_sor_set_parent_clock(sor, sor->clk_pad);
2579 if (err < 0) {
2580 dev_err(sor->dev, "failed to set pad clock: %d\n", err);
2581 return;
2582 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002583
Thierry Reding36e90222017-10-12 19:14:21 +02002584 /* adjust clock rate for HDMI 2.0 modes */
2585 rate = clk_get_rate(sor->clk_parent);
2586
2587 if (mode->clock >= 340000)
2588 rate /= 2;
2589
2590 DRM_DEBUG_KMS("setting clock to %lu Hz, mode: %lu Hz\n", rate, pclk);
2591
2592 clk_set_rate(sor->clk, rate);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002593
Thierry Redingc57997b2017-10-12 19:12:57 +02002594 if (!sor->soc->has_nvdisplay) {
2595 value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002596
Thierry Redingc57997b2017-10-12 19:12:57 +02002597 /* XXX is this the proper check? */
2598 if (mode->clock < 75000)
2599 value |= SOR_INPUT_CONTROL_ARM_VIDEO_RANGE_LIMITED;
2600
2601 tegra_sor_writel(sor, value, SOR_INPUT_CONTROL);
2602 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002603
2604 max_ac = ((mode->htotal - mode->hdisplay) - SOR_REKEY - 18) / 32;
2605
2606 value = SOR_HDMI_CTRL_ENABLE | SOR_HDMI_CTRL_MAX_AC_PACKET(max_ac) |
2607 SOR_HDMI_CTRL_AUDIO_LAYOUT | SOR_HDMI_CTRL_REKEY(SOR_REKEY);
2608 tegra_sor_writel(sor, value, SOR_HDMI_CTRL);
2609
Thierry Redingc57997b2017-10-12 19:12:57 +02002610 if (!dc->soc->has_nvdisplay) {
2611 /* H_PULSE2 setup */
2612 pulse_start = h_ref_to_sync +
2613 (mode->hsync_end - mode->hsync_start) +
2614 (mode->htotal - mode->hsync_end) - 10;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002615
Thierry Redingc57997b2017-10-12 19:12:57 +02002616 value = PULSE_LAST_END_A | PULSE_QUAL_VACTIVE |
2617 PULSE_POLARITY_HIGH | PULSE_MODE_NORMAL;
2618 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002619
Thierry Redingc57997b2017-10-12 19:12:57 +02002620 value = PULSE_END(pulse_start + 8) | PULSE_START(pulse_start);
2621 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002622
Thierry Redingc57997b2017-10-12 19:12:57 +02002623 value = tegra_dc_readl(dc, DC_DISP_DISP_SIGNAL_OPTIONS0);
2624 value |= H_PULSE2_ENABLE;
2625 tegra_dc_writel(dc, value, DC_DISP_DISP_SIGNAL_OPTIONS0);
2626 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002627
2628 /* infoframe setup */
2629 err = tegra_sor_hdmi_setup_avi_infoframe(sor, mode);
2630 if (err < 0)
2631 dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
2632
2633 /* XXX HDMI audio support not implemented yet */
2634 tegra_sor_hdmi_disable_audio_infoframe(sor);
2635
2636 /* use single TMDS protocol */
2637 value = tegra_sor_readl(sor, SOR_STATE1);
2638 value &= ~SOR_STATE_ASY_PROTOCOL_MASK;
2639 value |= SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A;
2640 tegra_sor_writel(sor, value, SOR_STATE1);
2641
2642 /* power up pad calibration */
Thierry Reding880cee02017-10-12 19:04:17 +02002643 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002644 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
Thierry Reding880cee02017-10-12 19:04:17 +02002645 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002646
2647 /* production settings */
2648 settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000);
Dan Carpenterdb8b42f2015-08-17 17:37:03 +03002649 if (!settings) {
2650 dev_err(sor->dev, "no settings for pixel clock %d Hz\n",
2651 mode->clock * 1000);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002652 return;
2653 }
2654
Thierry Reding880cee02017-10-12 19:04:17 +02002655 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002656 value &= ~SOR_PLL0_ICHPMP_MASK;
Thierry Redingc57997b2017-10-12 19:12:57 +02002657 value &= ~SOR_PLL0_FILTER_MASK;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002658 value &= ~SOR_PLL0_VCOCAP_MASK;
2659 value |= SOR_PLL0_ICHPMP(settings->ichpmp);
Thierry Redingc57997b2017-10-12 19:12:57 +02002660 value |= SOR_PLL0_FILTER(settings->filter);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002661 value |= SOR_PLL0_VCOCAP(settings->vcocap);
Thierry Reding880cee02017-10-12 19:04:17 +02002662 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002663
Thierry Redingc57997b2017-10-12 19:12:57 +02002664 /* XXX not in TRM */
Thierry Reding880cee02017-10-12 19:04:17 +02002665 value = tegra_sor_readl(sor, sor->soc->regs->pll1);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002666 value &= ~SOR_PLL1_LOADADJ_MASK;
Thierry Redingc57997b2017-10-12 19:12:57 +02002667 value &= ~SOR_PLL1_TMDS_TERMADJ_MASK;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002668 value |= SOR_PLL1_LOADADJ(settings->loadadj);
Thierry Redingc57997b2017-10-12 19:12:57 +02002669 value |= SOR_PLL1_TMDS_TERMADJ(settings->tmds_termadj);
2670 value |= SOR_PLL1_TMDS_TERM;
Thierry Reding880cee02017-10-12 19:04:17 +02002671 tegra_sor_writel(sor, value, sor->soc->regs->pll1);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002672
Thierry Reding880cee02017-10-12 19:04:17 +02002673 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
Thierry Redingc57997b2017-10-12 19:12:57 +02002674 value &= ~SOR_PLL3_BG_TEMP_COEF_MASK;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002675 value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK;
Thierry Redingc57997b2017-10-12 19:12:57 +02002676 value &= ~SOR_PLL3_AVDD10_LEVEL_MASK;
2677 value &= ~SOR_PLL3_AVDD14_LEVEL_MASK;
2678 value |= SOR_PLL3_BG_TEMP_COEF(settings->bg_temp_coef);
2679 value |= SOR_PLL3_BG_VREF_LEVEL(settings->bg_vref_level);
2680 value |= SOR_PLL3_AVDD10_LEVEL(settings->avdd10_level);
2681 value |= SOR_PLL3_AVDD14_LEVEL(settings->avdd14_level);
Thierry Reding880cee02017-10-12 19:04:17 +02002682 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002683
Thierry Redingc57997b2017-10-12 19:12:57 +02002684 value = settings->drive_current[3] << 24 |
2685 settings->drive_current[2] << 16 |
2686 settings->drive_current[1] << 8 |
2687 settings->drive_current[0] << 0;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002688 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0);
2689
Thierry Redingc57997b2017-10-12 19:12:57 +02002690 value = settings->preemphasis[3] << 24 |
2691 settings->preemphasis[2] << 16 |
2692 settings->preemphasis[1] << 8 |
2693 settings->preemphasis[0] << 0;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002694 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
2695
Thierry Reding880cee02017-10-12 19:04:17 +02002696 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002697 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
2698 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
Thierry Redingc57997b2017-10-12 19:12:57 +02002699 value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu_value);
Thierry Reding880cee02017-10-12 19:04:17 +02002700 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002701
Thierry Redingc57997b2017-10-12 19:12:57 +02002702 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl2);
2703 value &= ~SOR_DP_PADCTL_SPAREPLL_MASK;
2704 value |= SOR_DP_PADCTL_SPAREPLL(settings->sparepll);
2705 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl2);
2706
Thierry Reding459cc2c2015-07-30 10:34:24 +02002707 /* power down pad calibration */
Thierry Reding880cee02017-10-12 19:04:17 +02002708 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002709 value |= SOR_DP_PADCTL_PAD_CAL_PD;
Thierry Reding880cee02017-10-12 19:04:17 +02002710 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002711
Thierry Redingc57997b2017-10-12 19:12:57 +02002712 if (!dc->soc->has_nvdisplay) {
2713 /* miscellaneous display controller settings */
2714 value = VSYNC_H_POSITION(1);
2715 tegra_dc_writel(dc, value, DC_DISP_DISP_TIMING_OPTIONS);
2716 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002717
2718 value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
2719 value &= ~DITHER_CONTROL_MASK;
2720 value &= ~BASE_COLOR_SIZE_MASK;
2721
Thierry Redingc31efa72015-09-08 16:09:22 +02002722 switch (state->bpc) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002723 case 6:
2724 value |= BASE_COLOR_SIZE_666;
2725 break;
2726
2727 case 8:
2728 value |= BASE_COLOR_SIZE_888;
2729 break;
2730
Thierry Redingc57997b2017-10-12 19:12:57 +02002731 case 10:
2732 value |= BASE_COLOR_SIZE_101010;
2733 break;
2734
2735 case 12:
2736 value |= BASE_COLOR_SIZE_121212;
2737 break;
2738
Thierry Reding459cc2c2015-07-30 10:34:24 +02002739 default:
Thierry Redingc31efa72015-09-08 16:09:22 +02002740 WARN(1, "%u bits-per-color not supported\n", state->bpc);
2741 value |= BASE_COLOR_SIZE_888;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002742 break;
2743 }
2744
2745 tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
2746
Thierry Redingc57997b2017-10-12 19:12:57 +02002747 /* XXX set display head owner */
2748 value = tegra_sor_readl(sor, SOR_STATE1);
2749 value &= ~SOR_STATE_ASY_OWNER_MASK;
2750 value |= SOR_STATE_ASY_OWNER(1 + dc->pipe);
2751 tegra_sor_writel(sor, value, SOR_STATE1);
2752
Thierry Reding459cc2c2015-07-30 10:34:24 +02002753 err = tegra_sor_power_up(sor, 250);
2754 if (err < 0)
2755 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
2756
Thierry Reding2bd1dd32015-08-03 15:46:15 +02002757 /* configure dynamic range of output */
Thierry Reding880cee02017-10-12 19:04:17 +02002758 value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002759 value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK;
2760 value &= ~SOR_HEAD_STATE_DYNRANGE_MASK;
Thierry Reding880cee02017-10-12 19:04:17 +02002761 tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002762
Thierry Reding2bd1dd32015-08-03 15:46:15 +02002763 /* configure colorspace */
Thierry Reding880cee02017-10-12 19:04:17 +02002764 value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002765 value &= ~SOR_HEAD_STATE_COLORSPACE_MASK;
2766 value |= SOR_HEAD_STATE_COLORSPACE_RGB;
Thierry Reding880cee02017-10-12 19:04:17 +02002767 tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002768
Thierry Redingc31efa72015-09-08 16:09:22 +02002769 tegra_sor_mode_set(sor, mode, state);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002770
2771 tegra_sor_update(sor);
2772
Thierry Redingc57997b2017-10-12 19:12:57 +02002773 /* program preamble timing in SOR (XXX) */
2774 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
2775 value &= ~SOR_DP_SPARE_DISP_VIDEO_PREAMBLE;
2776 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
2777
Thierry Reding459cc2c2015-07-30 10:34:24 +02002778 err = tegra_sor_attach(sor);
2779 if (err < 0)
2780 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
2781
2782 /* enable display to SOR clock and generate HDMI preamble */
2783 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc57997b2017-10-12 19:12:57 +02002784
2785 if (!sor->soc->has_nvdisplay)
2786 value |= SOR_ENABLE(1) | SOR1_TIMING_CYA;
2787 else
2788 value |= SOR_ENABLE(sor->index);
2789
Thierry Reding459cc2c2015-07-30 10:34:24 +02002790 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
2791
Thierry Redingc57997b2017-10-12 19:12:57 +02002792 if (dc->soc->has_nvdisplay) {
2793 value = tegra_dc_readl(dc, DC_DISP_CORE_SOR_SET_CONTROL(sor->index));
2794 value &= ~PROTOCOL_MASK;
2795 value |= PROTOCOL_SINGLE_TMDS_A;
2796 tegra_dc_writel(dc, value, DC_DISP_CORE_SOR_SET_CONTROL(sor->index));
2797 }
2798
Thierry Reding459cc2c2015-07-30 10:34:24 +02002799 tegra_dc_commit(dc);
2800
2801 err = tegra_sor_wakeup(sor);
2802 if (err < 0)
2803 dev_err(sor->dev, "failed to wakeup SOR: %d\n", err);
Thierry Reding36e90222017-10-12 19:14:21 +02002804
2805 tegra_sor_hdmi_scdc_start(sor);
Thierry Reding8e2988a72018-12-03 15:46:03 +01002806 tegra_sor_audio_prepare(sor);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002807}
2808
2809static const struct drm_encoder_helper_funcs tegra_sor_hdmi_helpers = {
2810 .disable = tegra_sor_hdmi_disable,
2811 .enable = tegra_sor_hdmi_enable,
2812 .atomic_check = tegra_sor_encoder_atomic_check,
2813};
2814
Thierry Reding6b6b6042013-11-15 16:06:05 +01002815static int tegra_sor_init(struct host1x_client *client)
2816{
Thierry Reding9910f5c2014-05-22 09:57:15 +02002817 struct drm_device *drm = dev_get_drvdata(client->parent);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002818 const struct drm_encoder_helper_funcs *helpers = NULL;
Thierry Reding6b6b6042013-11-15 16:06:05 +01002819 struct tegra_sor *sor = host1x_client_to_sor(client);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002820 int connector = DRM_MODE_CONNECTOR_Unknown;
2821 int encoder = DRM_MODE_ENCODER_NONE;
Thierry Reding8e2988a72018-12-03 15:46:03 +01002822 u32 value;
Thierry Reding6b6b6042013-11-15 16:06:05 +01002823 int err;
2824
Thierry Reding9542c232015-07-08 13:39:09 +02002825 if (!sor->aux) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002826 if (sor->soc->supports_hdmi) {
2827 connector = DRM_MODE_CONNECTOR_HDMIA;
2828 encoder = DRM_MODE_ENCODER_TMDS;
2829 helpers = &tegra_sor_hdmi_helpers;
2830 } else if (sor->soc->supports_lvds) {
2831 connector = DRM_MODE_CONNECTOR_LVDS;
2832 encoder = DRM_MODE_ENCODER_LVDS;
2833 }
2834 } else {
2835 if (sor->soc->supports_edp) {
2836 connector = DRM_MODE_CONNECTOR_eDP;
2837 encoder = DRM_MODE_ENCODER_TMDS;
2838 helpers = &tegra_sor_edp_helpers;
2839 } else if (sor->soc->supports_dp) {
2840 connector = DRM_MODE_CONNECTOR_DisplayPort;
2841 encoder = DRM_MODE_ENCODER_TMDS;
2842 }
2843 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002844
Thierry Reding6b6b6042013-11-15 16:06:05 +01002845 sor->output.dev = sor->dev;
Thierry Reding6b6b6042013-11-15 16:06:05 +01002846
Thierry Reding6fad8f62014-11-28 15:41:34 +01002847 drm_connector_init(drm, &sor->output.connector,
2848 &tegra_sor_connector_funcs,
Thierry Reding459cc2c2015-07-30 10:34:24 +02002849 connector);
Thierry Reding6fad8f62014-11-28 15:41:34 +01002850 drm_connector_helper_add(&sor->output.connector,
2851 &tegra_sor_connector_helper_funcs);
2852 sor->output.connector.dpms = DRM_MODE_DPMS_OFF;
2853
Thierry Reding6fad8f62014-11-28 15:41:34 +01002854 drm_encoder_init(drm, &sor->output.encoder, &tegra_sor_encoder_funcs,
Ville Syrjälä13a3d912015-12-09 16:20:18 +02002855 encoder, NULL);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002856 drm_encoder_helper_add(&sor->output.encoder, helpers);
Thierry Reding6fad8f62014-11-28 15:41:34 +01002857
Daniel Vettercde4c442018-07-09 10:40:07 +02002858 drm_connector_attach_encoder(&sor->output.connector,
Thierry Reding6fad8f62014-11-28 15:41:34 +01002859 &sor->output.encoder);
2860 drm_connector_register(&sor->output.connector);
2861
Thierry Redingea130b22014-12-19 15:51:35 +01002862 err = tegra_output_init(drm, &sor->output);
2863 if (err < 0) {
2864 dev_err(client->dev, "failed to initialize output: %d\n", err);
2865 return err;
2866 }
Thierry Reding6fad8f62014-11-28 15:41:34 +01002867
Thierry Redingc57997b2017-10-12 19:12:57 +02002868 tegra_output_find_possible_crtcs(&sor->output, drm);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002869
Thierry Reding9542c232015-07-08 13:39:09 +02002870 if (sor->aux) {
2871 err = drm_dp_aux_attach(sor->aux, &sor->output);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002872 if (err < 0) {
2873 dev_err(sor->dev, "failed to attach DP: %d\n", err);
2874 return err;
2875 }
2876 }
2877
Tomeu Vizoso535a65d2015-03-30 10:33:03 +02002878 /*
2879 * XXX: Remove this reset once proper hand-over from firmware to
2880 * kernel is possible.
2881 */
Jon Hunterf8c79122016-07-01 14:21:38 +01002882 if (sor->rst) {
2883 err = reset_control_assert(sor->rst);
2884 if (err < 0) {
2885 dev_err(sor->dev, "failed to assert SOR reset: %d\n",
2886 err);
2887 return err;
2888 }
Tomeu Vizoso535a65d2015-03-30 10:33:03 +02002889 }
2890
Thierry Reding6fad8f62014-11-28 15:41:34 +01002891 err = clk_prepare_enable(sor->clk);
2892 if (err < 0) {
2893 dev_err(sor->dev, "failed to enable clock: %d\n", err);
2894 return err;
2895 }
2896
Tomeu Vizoso535a65d2015-03-30 10:33:03 +02002897 usleep_range(1000, 3000);
2898
Jon Hunterf8c79122016-07-01 14:21:38 +01002899 if (sor->rst) {
2900 err = reset_control_deassert(sor->rst);
2901 if (err < 0) {
2902 dev_err(sor->dev, "failed to deassert SOR reset: %d\n",
2903 err);
2904 return err;
2905 }
Tomeu Vizoso535a65d2015-03-30 10:33:03 +02002906 }
2907
Thierry Reding6fad8f62014-11-28 15:41:34 +01002908 err = clk_prepare_enable(sor->clk_safe);
2909 if (err < 0)
2910 return err;
2911
2912 err = clk_prepare_enable(sor->clk_dp);
2913 if (err < 0)
2914 return err;
2915
Thierry Reding8e2988a72018-12-03 15:46:03 +01002916 /*
2917 * Enable and unmask the HDA codec SCRATCH0 register interrupt. This
2918 * is used for interoperability between the HDA codec driver and the
2919 * HDMI/DP driver.
2920 */
2921 value = SOR_INT_CODEC_SCRATCH1 | SOR_INT_CODEC_SCRATCH0;
2922 tegra_sor_writel(sor, value, SOR_INT_ENABLE);
2923 tegra_sor_writel(sor, value, SOR_INT_MASK);
2924
Thierry Reding6b6b6042013-11-15 16:06:05 +01002925 return 0;
2926}
2927
2928static int tegra_sor_exit(struct host1x_client *client)
2929{
2930 struct tegra_sor *sor = host1x_client_to_sor(client);
2931 int err;
2932
Thierry Reding8e2988a72018-12-03 15:46:03 +01002933 tegra_sor_writel(sor, 0, SOR_INT_MASK);
2934 tegra_sor_writel(sor, 0, SOR_INT_ENABLE);
2935
Thierry Reding328ec692014-12-19 15:55:08 +01002936 tegra_output_exit(&sor->output);
2937
Thierry Reding9542c232015-07-08 13:39:09 +02002938 if (sor->aux) {
2939 err = drm_dp_aux_detach(sor->aux);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002940 if (err < 0) {
2941 dev_err(sor->dev, "failed to detach DP: %d\n", err);
2942 return err;
2943 }
2944 }
2945
Thierry Reding6fad8f62014-11-28 15:41:34 +01002946 clk_disable_unprepare(sor->clk_safe);
2947 clk_disable_unprepare(sor->clk_dp);
2948 clk_disable_unprepare(sor->clk);
2949
Thierry Reding6b6b6042013-11-15 16:06:05 +01002950 return 0;
2951}
2952
2953static const struct host1x_client_ops sor_client_ops = {
2954 .init = tegra_sor_init,
2955 .exit = tegra_sor_exit,
2956};
2957
Thierry Reding459cc2c2015-07-30 10:34:24 +02002958static const struct tegra_sor_ops tegra_sor_edp_ops = {
2959 .name = "eDP",
2960};
2961
2962static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
2963{
2964 int err;
2965
2966 sor->avdd_io_supply = devm_regulator_get(sor->dev, "avdd-io");
2967 if (IS_ERR(sor->avdd_io_supply)) {
2968 dev_err(sor->dev, "cannot get AVDD I/O supply: %ld\n",
2969 PTR_ERR(sor->avdd_io_supply));
2970 return PTR_ERR(sor->avdd_io_supply);
2971 }
2972
2973 err = regulator_enable(sor->avdd_io_supply);
2974 if (err < 0) {
2975 dev_err(sor->dev, "failed to enable AVDD I/O supply: %d\n",
2976 err);
2977 return err;
2978 }
2979
2980 sor->vdd_pll_supply = devm_regulator_get(sor->dev, "vdd-pll");
2981 if (IS_ERR(sor->vdd_pll_supply)) {
2982 dev_err(sor->dev, "cannot get VDD PLL supply: %ld\n",
2983 PTR_ERR(sor->vdd_pll_supply));
2984 return PTR_ERR(sor->vdd_pll_supply);
2985 }
2986
2987 err = regulator_enable(sor->vdd_pll_supply);
2988 if (err < 0) {
2989 dev_err(sor->dev, "failed to enable VDD PLL supply: %d\n",
2990 err);
2991 return err;
2992 }
2993
2994 sor->hdmi_supply = devm_regulator_get(sor->dev, "hdmi");
2995 if (IS_ERR(sor->hdmi_supply)) {
2996 dev_err(sor->dev, "cannot get HDMI supply: %ld\n",
2997 PTR_ERR(sor->hdmi_supply));
2998 return PTR_ERR(sor->hdmi_supply);
2999 }
3000
3001 err = regulator_enable(sor->hdmi_supply);
3002 if (err < 0) {
3003 dev_err(sor->dev, "failed to enable HDMI supply: %d\n", err);
3004 return err;
3005 }
3006
Thierry Reding36e90222017-10-12 19:14:21 +02003007 INIT_DELAYED_WORK(&sor->scdc, tegra_sor_hdmi_scdc_work);
3008
Thierry Reding459cc2c2015-07-30 10:34:24 +02003009 return 0;
3010}
3011
3012static int tegra_sor_hdmi_remove(struct tegra_sor *sor)
3013{
3014 regulator_disable(sor->hdmi_supply);
3015 regulator_disable(sor->vdd_pll_supply);
3016 regulator_disable(sor->avdd_io_supply);
3017
3018 return 0;
3019}
3020
3021static const struct tegra_sor_ops tegra_sor_hdmi_ops = {
3022 .name = "HDMI",
3023 .probe = tegra_sor_hdmi_probe,
3024 .remove = tegra_sor_hdmi_remove,
3025};
3026
Thierry Reding30b49432015-08-03 15:50:32 +02003027static const u8 tegra124_sor_xbar_cfg[5] = {
3028 0, 1, 2, 3, 4
3029};
3030
Thierry Reding880cee02017-10-12 19:04:17 +02003031static const struct tegra_sor_regs tegra124_sor_regs = {
3032 .head_state0 = 0x05,
3033 .head_state1 = 0x07,
3034 .head_state2 = 0x09,
3035 .head_state3 = 0x0b,
3036 .head_state4 = 0x0d,
3037 .head_state5 = 0x0f,
3038 .pll0 = 0x17,
3039 .pll1 = 0x18,
3040 .pll2 = 0x19,
3041 .pll3 = 0x1a,
3042 .dp_padctl0 = 0x5c,
3043 .dp_padctl2 = 0x73,
3044};
3045
Thierry Reding459cc2c2015-07-30 10:34:24 +02003046static const struct tegra_sor_soc tegra124_sor = {
3047 .supports_edp = true,
3048 .supports_lvds = true,
3049 .supports_hdmi = false,
3050 .supports_dp = false,
Thierry Reding880cee02017-10-12 19:04:17 +02003051 .regs = &tegra124_sor_regs,
Thierry Redingc57997b2017-10-12 19:12:57 +02003052 .has_nvdisplay = false,
Thierry Reding30b49432015-08-03 15:50:32 +02003053 .xbar_cfg = tegra124_sor_xbar_cfg,
Thierry Reding459cc2c2015-07-30 10:34:24 +02003054};
3055
Thierry Reding880cee02017-10-12 19:04:17 +02003056static const struct tegra_sor_regs tegra210_sor_regs = {
3057 .head_state0 = 0x05,
3058 .head_state1 = 0x07,
3059 .head_state2 = 0x09,
3060 .head_state3 = 0x0b,
3061 .head_state4 = 0x0d,
3062 .head_state5 = 0x0f,
3063 .pll0 = 0x17,
3064 .pll1 = 0x18,
3065 .pll2 = 0x19,
3066 .pll3 = 0x1a,
3067 .dp_padctl0 = 0x5c,
3068 .dp_padctl2 = 0x73,
3069};
3070
Thierry Reding459cc2c2015-07-30 10:34:24 +02003071static const struct tegra_sor_soc tegra210_sor = {
3072 .supports_edp = true,
3073 .supports_lvds = false,
3074 .supports_hdmi = false,
3075 .supports_dp = false,
Thierry Reding880cee02017-10-12 19:04:17 +02003076 .regs = &tegra210_sor_regs,
Thierry Redingc57997b2017-10-12 19:12:57 +02003077 .has_nvdisplay = false,
Thierry Reding30b49432015-08-03 15:50:32 +02003078 .xbar_cfg = tegra124_sor_xbar_cfg,
3079};
3080
3081static const u8 tegra210_sor_xbar_cfg[5] = {
3082 2, 1, 0, 3, 4
Thierry Reding459cc2c2015-07-30 10:34:24 +02003083};
3084
3085static const struct tegra_sor_soc tegra210_sor1 = {
3086 .supports_edp = false,
3087 .supports_lvds = false,
3088 .supports_hdmi = true,
3089 .supports_dp = true,
3090
Thierry Reding880cee02017-10-12 19:04:17 +02003091 .regs = &tegra210_sor_regs,
Thierry Redingc57997b2017-10-12 19:12:57 +02003092 .has_nvdisplay = false,
Thierry Reding880cee02017-10-12 19:04:17 +02003093
Thierry Reding459cc2c2015-07-30 10:34:24 +02003094 .num_settings = ARRAY_SIZE(tegra210_sor_hdmi_defaults),
3095 .settings = tegra210_sor_hdmi_defaults,
Thierry Reding30b49432015-08-03 15:50:32 +02003096
3097 .xbar_cfg = tegra210_sor_xbar_cfg,
Thierry Reding459cc2c2015-07-30 10:34:24 +02003098};
3099
Thierry Redingc57997b2017-10-12 19:12:57 +02003100static const struct tegra_sor_regs tegra186_sor_regs = {
3101 .head_state0 = 0x151,
3102 .head_state1 = 0x154,
3103 .head_state2 = 0x157,
3104 .head_state3 = 0x15a,
3105 .head_state4 = 0x15d,
3106 .head_state5 = 0x160,
3107 .pll0 = 0x163,
3108 .pll1 = 0x164,
3109 .pll2 = 0x165,
3110 .pll3 = 0x166,
3111 .dp_padctl0 = 0x168,
3112 .dp_padctl2 = 0x16a,
3113};
3114
3115static const struct tegra_sor_soc tegra186_sor = {
3116 .supports_edp = false,
3117 .supports_lvds = false,
3118 .supports_hdmi = false,
3119 .supports_dp = true,
3120
3121 .regs = &tegra186_sor_regs,
3122 .has_nvdisplay = true,
3123
3124 .xbar_cfg = tegra124_sor_xbar_cfg,
3125};
3126
3127static const struct tegra_sor_soc tegra186_sor1 = {
3128 .supports_edp = false,
3129 .supports_lvds = false,
3130 .supports_hdmi = true,
3131 .supports_dp = true,
3132
3133 .regs = &tegra186_sor_regs,
3134 .has_nvdisplay = true,
3135
3136 .num_settings = ARRAY_SIZE(tegra186_sor_hdmi_defaults),
3137 .settings = tegra186_sor_hdmi_defaults,
3138
3139 .xbar_cfg = tegra124_sor_xbar_cfg,
3140};
3141
Thierry Reding9b6c14b2018-09-21 12:27:46 +02003142static const struct tegra_sor_regs tegra194_sor_regs = {
3143 .head_state0 = 0x151,
3144 .head_state1 = 0x155,
3145 .head_state2 = 0x159,
3146 .head_state3 = 0x15d,
3147 .head_state4 = 0x161,
3148 .head_state5 = 0x165,
3149 .pll0 = 0x169,
3150 .pll1 = 0x16a,
3151 .pll2 = 0x16b,
3152 .pll3 = 0x16c,
3153 .dp_padctl0 = 0x16e,
3154 .dp_padctl2 = 0x16f,
3155};
3156
3157static const struct tegra_sor_soc tegra194_sor = {
3158 .supports_edp = true,
3159 .supports_lvds = false,
3160 .supports_hdmi = true,
3161 .supports_dp = true,
3162
3163 .regs = &tegra194_sor_regs,
3164 .has_nvdisplay = true,
3165
3166 .num_settings = ARRAY_SIZE(tegra194_sor_hdmi_defaults),
3167 .settings = tegra194_sor_hdmi_defaults,
3168
3169 .xbar_cfg = tegra210_sor_xbar_cfg,
3170};
3171
Thierry Reding459cc2c2015-07-30 10:34:24 +02003172static const struct of_device_id tegra_sor_of_match[] = {
Thierry Reding9b6c14b2018-09-21 12:27:46 +02003173 { .compatible = "nvidia,tegra194-sor", .data = &tegra194_sor },
Thierry Redingc57997b2017-10-12 19:12:57 +02003174 { .compatible = "nvidia,tegra186-sor1", .data = &tegra186_sor1 },
3175 { .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor },
Thierry Reding459cc2c2015-07-30 10:34:24 +02003176 { .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 },
3177 { .compatible = "nvidia,tegra210-sor", .data = &tegra210_sor },
3178 { .compatible = "nvidia,tegra124-sor", .data = &tegra124_sor },
3179 { },
3180};
3181MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
3182
Thierry Redingc57997b2017-10-12 19:12:57 +02003183static int tegra_sor_parse_dt(struct tegra_sor *sor)
3184{
3185 struct device_node *np = sor->dev->of_node;
3186 u32 value;
3187 int err;
3188
3189 if (sor->soc->has_nvdisplay) {
3190 err = of_property_read_u32(np, "nvidia,interface", &value);
3191 if (err < 0)
3192 return err;
3193
3194 sor->index = value;
3195
3196 /*
3197 * override the default that we already set for Tegra210 and
3198 * earlier
3199 */
3200 sor->pad = TEGRA_IO_PAD_HDMI_DP0 + sor->index;
3201 }
3202
3203 return 0;
3204}
3205
Thierry Reding8e2988a72018-12-03 15:46:03 +01003206static void tegra_hda_parse_format(unsigned int format, unsigned int *rate,
3207 unsigned int *channels)
3208{
3209 unsigned int mul, div;
3210
3211 if (format & AC_FMT_BASE_44K)
3212 *rate = 44100;
3213 else
3214 *rate = 48000;
3215
3216 mul = (format & AC_FMT_MULT_MASK) >> AC_FMT_MULT_SHIFT;
3217 div = (format & AC_FMT_DIV_MASK) >> AC_FMT_DIV_SHIFT;
3218
3219 *rate = *rate * (mul + 1) / (div + 1);
3220
3221 *channels = (format & AC_FMT_CHAN_MASK) >> AC_FMT_CHAN_SHIFT;
3222}
3223
3224static irqreturn_t tegra_sor_irq(int irq, void *data)
3225{
3226 struct tegra_sor *sor = data;
3227 u32 value;
3228
3229 value = tegra_sor_readl(sor, SOR_INT_STATUS);
3230 tegra_sor_writel(sor, value, SOR_INT_STATUS);
3231
3232 if (value & SOR_INT_CODEC_SCRATCH0) {
3233 value = tegra_sor_readl(sor, SOR_AUDIO_HDA_CODEC_SCRATCH0);
3234
3235 if (value & SOR_AUDIO_HDA_CODEC_SCRATCH0_VALID) {
3236 unsigned int format, sample_rate, channels;
3237
3238 format = value & SOR_AUDIO_HDA_CODEC_SCRATCH0_FMT_MASK;
3239
3240 tegra_hda_parse_format(format, &sample_rate, &channels);
3241
3242 sor->audio.sample_rate = sample_rate;
3243 sor->audio.channels = channels;
3244
3245 tegra_sor_hdmi_audio_enable(sor);
3246 } else {
3247 tegra_sor_hdmi_audio_disable(sor);
3248 }
3249 }
3250
3251 return IRQ_HANDLED;
3252}
3253
Thierry Reding6b6b6042013-11-15 16:06:05 +01003254static int tegra_sor_probe(struct platform_device *pdev)
3255{
3256 struct device_node *np;
3257 struct tegra_sor *sor;
3258 struct resource *regs;
3259 int err;
3260
3261 sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL);
3262 if (!sor)
3263 return -ENOMEM;
3264
Thierry Reding5faea3d2017-08-21 17:33:14 +02003265 sor->soc = of_device_get_match_data(&pdev->dev);
Thierry Reding6b6b6042013-11-15 16:06:05 +01003266 sor->output.dev = sor->dev = &pdev->dev;
Thierry Reding459cc2c2015-07-30 10:34:24 +02003267
3268 sor->settings = devm_kmemdup(&pdev->dev, sor->soc->settings,
3269 sor->soc->num_settings *
3270 sizeof(*sor->settings),
3271 GFP_KERNEL);
3272 if (!sor->settings)
3273 return -ENOMEM;
3274
3275 sor->num_settings = sor->soc->num_settings;
Thierry Reding6b6b6042013-11-15 16:06:05 +01003276
3277 np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
3278 if (np) {
Thierry Reding9542c232015-07-08 13:39:09 +02003279 sor->aux = drm_dp_aux_find_by_of_node(np);
Thierry Reding6b6b6042013-11-15 16:06:05 +01003280 of_node_put(np);
3281
Thierry Reding9542c232015-07-08 13:39:09 +02003282 if (!sor->aux)
Thierry Reding6b6b6042013-11-15 16:06:05 +01003283 return -EPROBE_DEFER;
3284 }
3285
Thierry Reding9542c232015-07-08 13:39:09 +02003286 if (!sor->aux) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02003287 if (sor->soc->supports_hdmi) {
3288 sor->ops = &tegra_sor_hdmi_ops;
Thierry Redingc57997b2017-10-12 19:12:57 +02003289 sor->pad = TEGRA_IO_PAD_HDMI;
Thierry Reding459cc2c2015-07-30 10:34:24 +02003290 } else if (sor->soc->supports_lvds) {
3291 dev_err(&pdev->dev, "LVDS not supported yet\n");
3292 return -ENODEV;
3293 } else {
3294 dev_err(&pdev->dev, "unknown (non-DP) support\n");
3295 return -ENODEV;
3296 }
3297 } else {
3298 if (sor->soc->supports_edp) {
3299 sor->ops = &tegra_sor_edp_ops;
Thierry Redingc57997b2017-10-12 19:12:57 +02003300 sor->pad = TEGRA_IO_PAD_LVDS;
Thierry Reding459cc2c2015-07-30 10:34:24 +02003301 } else if (sor->soc->supports_dp) {
3302 dev_err(&pdev->dev, "DisplayPort not supported yet\n");
3303 return -ENODEV;
3304 } else {
3305 dev_err(&pdev->dev, "unknown (DP) support\n");
3306 return -ENODEV;
3307 }
3308 }
3309
Thierry Redingc57997b2017-10-12 19:12:57 +02003310 err = tegra_sor_parse_dt(sor);
3311 if (err < 0)
3312 return err;
3313
Thierry Reding6b6b6042013-11-15 16:06:05 +01003314 err = tegra_output_probe(&sor->output);
Thierry Reding4dbdc742015-04-27 15:04:26 +02003315 if (err < 0) {
3316 dev_err(&pdev->dev, "failed to probe output: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01003317 return err;
Thierry Reding4dbdc742015-04-27 15:04:26 +02003318 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01003319
Thierry Reding459cc2c2015-07-30 10:34:24 +02003320 if (sor->ops && sor->ops->probe) {
3321 err = sor->ops->probe(sor);
3322 if (err < 0) {
3323 dev_err(&pdev->dev, "failed to probe %s: %d\n",
3324 sor->ops->name, err);
3325 goto output;
3326 }
3327 }
3328
Thierry Reding6b6b6042013-11-15 16:06:05 +01003329 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3330 sor->regs = devm_ioremap_resource(&pdev->dev, regs);
Thierry Reding459cc2c2015-07-30 10:34:24 +02003331 if (IS_ERR(sor->regs)) {
3332 err = PTR_ERR(sor->regs);
3333 goto remove;
3334 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01003335
Thierry Reding8e2988a72018-12-03 15:46:03 +01003336 err = platform_get_irq(pdev, 0);
3337 if (err < 0) {
3338 dev_err(&pdev->dev, "failed to get IRQ: %d\n", err);
3339 goto remove;
3340 }
3341
3342 sor->irq = err;
3343
3344 err = devm_request_irq(sor->dev, sor->irq, tegra_sor_irq, 0,
3345 dev_name(sor->dev), sor);
3346 if (err < 0) {
3347 dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
3348 goto remove;
3349 }
3350
Jon Hunterf8c79122016-07-01 14:21:38 +01003351 if (!pdev->dev.pm_domain) {
3352 sor->rst = devm_reset_control_get(&pdev->dev, "sor");
3353 if (IS_ERR(sor->rst)) {
3354 err = PTR_ERR(sor->rst);
3355 dev_err(&pdev->dev, "failed to get reset control: %d\n",
3356 err);
3357 goto remove;
3358 }
Thierry Reding4dbdc742015-04-27 15:04:26 +02003359 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01003360
3361 sor->clk = devm_clk_get(&pdev->dev, NULL);
Thierry Reding4dbdc742015-04-27 15:04:26 +02003362 if (IS_ERR(sor->clk)) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02003363 err = PTR_ERR(sor->clk);
3364 dev_err(&pdev->dev, "failed to get module clock: %d\n", err);
3365 goto remove;
Thierry Reding4dbdc742015-04-27 15:04:26 +02003366 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01003367
Thierry Reding618dee32016-06-09 17:53:57 +02003368 if (sor->soc->supports_hdmi || sor->soc->supports_dp) {
Thierry Redinge1335e22017-10-12 17:53:11 +02003369 struct device_node *np = pdev->dev.of_node;
3370 const char *name;
3371
3372 /*
3373 * For backwards compatibility with Tegra210 device trees,
3374 * fall back to the old clock name "source" if the new "out"
3375 * clock is not available.
3376 */
3377 if (of_property_match_string(np, "clock-names", "out") < 0)
3378 name = "source";
3379 else
3380 name = "out";
3381
3382 sor->clk_out = devm_clk_get(&pdev->dev, name);
3383 if (IS_ERR(sor->clk_out)) {
3384 err = PTR_ERR(sor->clk_out);
3385 dev_err(sor->dev, "failed to get %s clock: %d\n",
3386 name, err);
Thierry Reding618dee32016-06-09 17:53:57 +02003387 goto remove;
3388 }
Thierry Reding1087fac2017-12-14 13:37:53 +01003389 } else {
Thierry Redingd7805372018-01-10 13:04:58 +01003390 /* fall back to the module clock on SOR0 (eDP/LVDS only) */
Thierry Reding1087fac2017-12-14 13:37:53 +01003391 sor->clk_out = sor->clk;
Thierry Reding618dee32016-06-09 17:53:57 +02003392 }
3393
Thierry Reding6b6b6042013-11-15 16:06:05 +01003394 sor->clk_parent = devm_clk_get(&pdev->dev, "parent");
Thierry Reding4dbdc742015-04-27 15:04:26 +02003395 if (IS_ERR(sor->clk_parent)) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02003396 err = PTR_ERR(sor->clk_parent);
3397 dev_err(&pdev->dev, "failed to get parent clock: %d\n", err);
3398 goto remove;
Thierry Reding4dbdc742015-04-27 15:04:26 +02003399 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01003400
Thierry Reding6b6b6042013-11-15 16:06:05 +01003401 sor->clk_safe = devm_clk_get(&pdev->dev, "safe");
Thierry Reding4dbdc742015-04-27 15:04:26 +02003402 if (IS_ERR(sor->clk_safe)) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02003403 err = PTR_ERR(sor->clk_safe);
3404 dev_err(&pdev->dev, "failed to get safe clock: %d\n", err);
3405 goto remove;
Thierry Reding4dbdc742015-04-27 15:04:26 +02003406 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01003407
Thierry Reding6b6b6042013-11-15 16:06:05 +01003408 sor->clk_dp = devm_clk_get(&pdev->dev, "dp");
Thierry Reding4dbdc742015-04-27 15:04:26 +02003409 if (IS_ERR(sor->clk_dp)) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02003410 err = PTR_ERR(sor->clk_dp);
3411 dev_err(&pdev->dev, "failed to get DP clock: %d\n", err);
3412 goto remove;
Thierry Reding4dbdc742015-04-27 15:04:26 +02003413 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01003414
Thierry Redinge1335e22017-10-12 17:53:11 +02003415 /*
3416 * Starting with Tegra186, the BPMP provides an implementation for
3417 * the pad output clock, so we have to look it up from device tree.
3418 */
3419 sor->clk_pad = devm_clk_get(&pdev->dev, "pad");
3420 if (IS_ERR(sor->clk_pad)) {
3421 if (sor->clk_pad != ERR_PTR(-ENOENT)) {
3422 err = PTR_ERR(sor->clk_pad);
3423 goto remove;
3424 }
3425
3426 /*
3427 * If the pad output clock is not available, then we assume
3428 * we're on Tegra210 or earlier and have to provide our own
3429 * implementation.
3430 */
3431 sor->clk_pad = NULL;
3432 }
3433
3434 /*
3435 * The bootloader may have set up the SOR such that it's module clock
3436 * is sourced by one of the display PLLs. However, that doesn't work
3437 * without properly having set up other bits of the SOR.
3438 */
3439 err = clk_set_parent(sor->clk_out, sor->clk_safe);
3440 if (err < 0) {
3441 dev_err(&pdev->dev, "failed to use safe clock: %d\n", err);
3442 goto remove;
3443 }
3444
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003445 platform_set_drvdata(pdev, sor);
3446 pm_runtime_enable(&pdev->dev);
3447
Thierry Redinge1335e22017-10-12 17:53:11 +02003448 /*
3449 * On Tegra210 and earlier, provide our own implementation for the
3450 * pad output clock.
3451 */
3452 if (!sor->clk_pad) {
3453 err = pm_runtime_get_sync(&pdev->dev);
3454 if (err < 0) {
3455 dev_err(&pdev->dev, "failed to get runtime PM: %d\n",
3456 err);
3457 goto remove;
3458 }
Thierry Redingb2992212015-10-01 14:25:03 +02003459
Thierry Redinge1335e22017-10-12 17:53:11 +02003460 sor->clk_pad = tegra_clk_sor_pad_register(sor,
3461 "sor1_pad_clkout");
3462 pm_runtime_put(&pdev->dev);
3463 }
3464
3465 if (IS_ERR(sor->clk_pad)) {
3466 err = PTR_ERR(sor->clk_pad);
3467 dev_err(&pdev->dev, "failed to register SOR pad clock: %d\n",
3468 err);
Thierry Redingb2992212015-10-01 14:25:03 +02003469 goto remove;
3470 }
3471
Thierry Reding6b6b6042013-11-15 16:06:05 +01003472 INIT_LIST_HEAD(&sor->client.list);
3473 sor->client.ops = &sor_client_ops;
3474 sor->client.dev = &pdev->dev;
3475
Thierry Reding6b6b6042013-11-15 16:06:05 +01003476 err = host1x_client_register(&sor->client);
3477 if (err < 0) {
3478 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
3479 err);
Thierry Reding459cc2c2015-07-30 10:34:24 +02003480 goto remove;
Thierry Reding6b6b6042013-11-15 16:06:05 +01003481 }
3482
Thierry Reding6b6b6042013-11-15 16:06:05 +01003483 return 0;
Thierry Reding459cc2c2015-07-30 10:34:24 +02003484
3485remove:
3486 if (sor->ops && sor->ops->remove)
3487 sor->ops->remove(sor);
3488output:
3489 tegra_output_remove(&sor->output);
3490 return err;
Thierry Reding6b6b6042013-11-15 16:06:05 +01003491}
3492
3493static int tegra_sor_remove(struct platform_device *pdev)
3494{
3495 struct tegra_sor *sor = platform_get_drvdata(pdev);
3496 int err;
3497
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003498 pm_runtime_disable(&pdev->dev);
3499
Thierry Reding6b6b6042013-11-15 16:06:05 +01003500 err = host1x_client_unregister(&sor->client);
3501 if (err < 0) {
3502 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
3503 err);
3504 return err;
3505 }
3506
Thierry Reding459cc2c2015-07-30 10:34:24 +02003507 if (sor->ops && sor->ops->remove) {
3508 err = sor->ops->remove(sor);
3509 if (err < 0)
3510 dev_err(&pdev->dev, "failed to remove SOR: %d\n", err);
3511 }
3512
Thierry Reding328ec692014-12-19 15:55:08 +01003513 tegra_output_remove(&sor->output);
Thierry Reding6b6b6042013-11-15 16:06:05 +01003514
3515 return 0;
3516}
3517
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003518#ifdef CONFIG_PM
3519static int tegra_sor_suspend(struct device *dev)
3520{
3521 struct tegra_sor *sor = dev_get_drvdata(dev);
3522 int err;
3523
Jon Hunterf8c79122016-07-01 14:21:38 +01003524 if (sor->rst) {
3525 err = reset_control_assert(sor->rst);
3526 if (err < 0) {
3527 dev_err(dev, "failed to assert reset: %d\n", err);
3528 return err;
3529 }
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003530 }
3531
3532 usleep_range(1000, 2000);
3533
3534 clk_disable_unprepare(sor->clk);
3535
3536 return 0;
3537}
3538
3539static int tegra_sor_resume(struct device *dev)
3540{
3541 struct tegra_sor *sor = dev_get_drvdata(dev);
3542 int err;
3543
3544 err = clk_prepare_enable(sor->clk);
3545 if (err < 0) {
3546 dev_err(dev, "failed to enable clock: %d\n", err);
3547 return err;
3548 }
3549
3550 usleep_range(1000, 2000);
3551
Jon Hunterf8c79122016-07-01 14:21:38 +01003552 if (sor->rst) {
3553 err = reset_control_deassert(sor->rst);
3554 if (err < 0) {
3555 dev_err(dev, "failed to deassert reset: %d\n", err);
3556 clk_disable_unprepare(sor->clk);
3557 return err;
3558 }
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003559 }
3560
3561 return 0;
3562}
3563#endif
3564
3565static const struct dev_pm_ops tegra_sor_pm_ops = {
3566 SET_RUNTIME_PM_OPS(tegra_sor_suspend, tegra_sor_resume, NULL)
3567};
3568
Thierry Reding6b6b6042013-11-15 16:06:05 +01003569struct platform_driver tegra_sor_driver = {
3570 .driver = {
3571 .name = "tegra-sor",
3572 .of_match_table = tegra_sor_of_match,
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003573 .pm = &tegra_sor_pm_ops,
Thierry Reding6b6b6042013-11-15 16:06:05 +01003574 },
3575 .probe = tegra_sor_probe,
3576 .remove = tegra_sor_remove,
3577};