blob: 1d7f24df0b10d9e9e1eaf367a7ec3a83ce566c99 [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 Reding4aa3df72014-11-24 16:27:13 +010022#include <drm/drm_atomic_helper.h>
Thierry Reding6b6b6042013-11-15 16:06:05 +010023#include <drm/drm_dp_helper.h>
Thierry Reding6fad8f62014-11-28 15:41:34 +010024#include <drm/drm_panel.h>
Thierry Reding6b6b6042013-11-15 16:06:05 +010025
26#include "dc.h"
27#include "drm.h"
28#include "sor.h"
Thierry Reding932f6522017-08-15 15:41:14 +020029#include "trace.h"
Thierry Reding6b6b6042013-11-15 16:06:05 +010030
Thierry Redingc57997b2017-10-12 19:12:57 +020031/*
32 * XXX Remove this after the commit adding it to soc/tegra/pmc.h has been
33 * merged. Having this around after the commit is merged should be safe since
34 * the preprocessor will effectively replace all occurrences and therefore no
35 * duplicate will be defined.
36 */
37#define TEGRA_IO_PAD_HDMI_DP0 26
38
Thierry Reding459cc2c2015-07-30 10:34:24 +020039#define SOR_REKEY 0x38
40
41struct tegra_sor_hdmi_settings {
42 unsigned long frequency;
43
44 u8 vcocap;
Thierry Redingc57997b2017-10-12 19:12:57 +020045 u8 filter;
Thierry Reding459cc2c2015-07-30 10:34:24 +020046 u8 ichpmp;
47 u8 loadadj;
Thierry Redingc57997b2017-10-12 19:12:57 +020048 u8 tmds_termadj;
49 u8 tx_pu_value;
50 u8 bg_temp_coef;
51 u8 bg_vref_level;
52 u8 avdd10_level;
53 u8 avdd14_level;
54 u8 sparepll;
Thierry Reding459cc2c2015-07-30 10:34:24 +020055
56 u8 drive_current[4];
57 u8 preemphasis[4];
58};
59
60#if 1
61static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
62 {
63 .frequency = 54000000,
64 .vcocap = 0x0,
Thierry Redingc57997b2017-10-12 19:12:57 +020065 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020066 .ichpmp = 0x1,
67 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020068 .tmds_termadj = 0x9,
69 .tx_pu_value = 0x10,
70 .bg_temp_coef = 0x3,
71 .bg_vref_level = 0x8,
72 .avdd10_level = 0x4,
73 .avdd14_level = 0x4,
74 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020075 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
76 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
77 }, {
78 .frequency = 75000000,
79 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020080 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020081 .ichpmp = 0x1,
82 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020083 .tmds_termadj = 0x9,
84 .tx_pu_value = 0x40,
85 .bg_temp_coef = 0x3,
86 .bg_vref_level = 0x8,
87 .avdd10_level = 0x4,
88 .avdd14_level = 0x4,
89 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020090 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
91 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
92 }, {
93 .frequency = 150000000,
94 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020095 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +020096 .ichpmp = 0x1,
97 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +020098 .tmds_termadj = 0x9,
99 .tx_pu_value = 0x66,
100 .bg_temp_coef = 0x3,
101 .bg_vref_level = 0x8,
102 .avdd10_level = 0x4,
103 .avdd14_level = 0x4,
104 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200105 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
106 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
107 }, {
108 .frequency = 300000000,
109 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200110 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200111 .ichpmp = 0x1,
112 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200113 .tmds_termadj = 0x9,
114 .tx_pu_value = 0x66,
115 .bg_temp_coef = 0x3,
116 .bg_vref_level = 0xa,
117 .avdd10_level = 0x4,
118 .avdd14_level = 0x4,
119 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200120 .drive_current = { 0x33, 0x3f, 0x3f, 0x3f },
121 .preemphasis = { 0x00, 0x17, 0x17, 0x17 },
122 }, {
123 .frequency = 600000000,
124 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200125 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200126 .ichpmp = 0x1,
127 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200128 .tmds_termadj = 0x9,
129 .tx_pu_value = 0x66,
130 .bg_temp_coef = 0x3,
131 .bg_vref_level = 0x8,
132 .avdd10_level = 0x4,
133 .avdd14_level = 0x4,
134 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200135 .drive_current = { 0x33, 0x3f, 0x3f, 0x3f },
136 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
137 },
138};
139#else
140static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
141 {
142 .frequency = 75000000,
143 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200144 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200145 .ichpmp = 0x1,
146 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200147 .tmds_termadj = 0x9,
148 .tx_pu_value = 0x40,
149 .bg_temp_coef = 0x3,
150 .bg_vref_level = 0x8,
151 .avdd10_level = 0x4,
152 .avdd14_level = 0x4,
153 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200154 .drive_current = { 0x29, 0x29, 0x29, 0x29 },
155 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
156 }, {
157 .frequency = 150000000,
158 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200159 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200160 .ichpmp = 0x1,
161 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200162 .tmds_termadj = 0x9,
163 .tx_pu_value = 0x66,
164 .bg_temp_coef = 0x3,
165 .bg_vref_level = 0x8,
166 .avdd10_level = 0x4,
167 .avdd14_level = 0x4,
168 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200169 .drive_current = { 0x30, 0x37, 0x37, 0x37 },
170 .preemphasis = { 0x01, 0x02, 0x02, 0x02 },
171 }, {
172 .frequency = 300000000,
173 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200174 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200175 .ichpmp = 0x6,
176 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200177 .tmds_termadj = 0x9,
178 .tx_pu_value = 0x66,
179 .bg_temp_coef = 0x3,
180 .bg_vref_level = 0xf,
181 .avdd10_level = 0x4,
182 .avdd14_level = 0x4,
183 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200184 .drive_current = { 0x30, 0x37, 0x37, 0x37 },
185 .preemphasis = { 0x10, 0x3e, 0x3e, 0x3e },
186 }, {
187 .frequency = 600000000,
188 .vcocap = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200189 .filter = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200190 .ichpmp = 0xa,
191 .loadadj = 0x3,
Thierry Redingc57997b2017-10-12 19:12:57 +0200192 .tmds_termadj = 0xb,
193 .tx_pu_value = 0x66,
194 .bg_temp_coef = 0x3,
195 .bg_vref_level = 0xe,
196 .avdd10_level = 0x4,
197 .avdd14_level = 0x4,
198 .sparepll = 0x0,
Thierry Reding459cc2c2015-07-30 10:34:24 +0200199 .drive_current = { 0x35, 0x3e, 0x3e, 0x3e },
200 .preemphasis = { 0x02, 0x3f, 0x3f, 0x3f },
201 },
202};
203#endif
204
Thierry Redingc57997b2017-10-12 19:12:57 +0200205static const struct tegra_sor_hdmi_settings tegra186_sor_hdmi_defaults[] = {
206 {
207 .frequency = 54000000,
208 .vcocap = 0,
209 .filter = 5,
210 .ichpmp = 5,
211 .loadadj = 3,
212 .tmds_termadj = 0xf,
213 .tx_pu_value = 0,
214 .bg_temp_coef = 3,
215 .bg_vref_level = 8,
216 .avdd10_level = 4,
217 .avdd14_level = 4,
218 .sparepll = 0x54,
219 .drive_current = { 0x3a, 0x3a, 0x3a, 0x33 },
220 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
221 }, {
222 .frequency = 75000000,
223 .vcocap = 1,
224 .filter = 5,
225 .ichpmp = 5,
226 .loadadj = 3,
227 .tmds_termadj = 0xf,
228 .tx_pu_value = 0,
229 .bg_temp_coef = 3,
230 .bg_vref_level = 8,
231 .avdd10_level = 4,
232 .avdd14_level = 4,
233 .sparepll = 0x44,
234 .drive_current = { 0x3a, 0x3a, 0x3a, 0x33 },
235 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
236 }, {
237 .frequency = 150000000,
238 .vcocap = 3,
239 .filter = 5,
240 .ichpmp = 5,
241 .loadadj = 3,
242 .tmds_termadj = 15,
243 .tx_pu_value = 0x66 /* 0 */,
244 .bg_temp_coef = 3,
245 .bg_vref_level = 8,
246 .avdd10_level = 4,
247 .avdd14_level = 4,
248 .sparepll = 0x00, /* 0x34 */
249 .drive_current = { 0x3a, 0x3a, 0x3a, 0x37 },
250 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
251 }, {
252 .frequency = 300000000,
253 .vcocap = 3,
254 .filter = 5,
255 .ichpmp = 5,
256 .loadadj = 3,
257 .tmds_termadj = 15,
258 .tx_pu_value = 64,
259 .bg_temp_coef = 3,
260 .bg_vref_level = 8,
261 .avdd10_level = 4,
262 .avdd14_level = 4,
263 .sparepll = 0x34,
264 .drive_current = { 0x3d, 0x3d, 0x3d, 0x33 },
265 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
266 }, {
267 .frequency = 600000000,
268 .vcocap = 3,
269 .filter = 5,
270 .ichpmp = 5,
271 .loadadj = 3,
272 .tmds_termadj = 12,
273 .tx_pu_value = 96,
274 .bg_temp_coef = 3,
275 .bg_vref_level = 8,
276 .avdd10_level = 4,
277 .avdd14_level = 4,
278 .sparepll = 0x34,
279 .drive_current = { 0x3d, 0x3d, 0x3d, 0x33 },
280 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
281 }
282};
283
Thierry Reding880cee02017-10-12 19:04:17 +0200284struct tegra_sor_regs {
285 unsigned int head_state0;
286 unsigned int head_state1;
287 unsigned int head_state2;
288 unsigned int head_state3;
289 unsigned int head_state4;
290 unsigned int head_state5;
291 unsigned int pll0;
292 unsigned int pll1;
293 unsigned int pll2;
294 unsigned int pll3;
295 unsigned int dp_padctl0;
296 unsigned int dp_padctl2;
297};
298
Thierry Reding459cc2c2015-07-30 10:34:24 +0200299struct tegra_sor_soc {
300 bool supports_edp;
301 bool supports_lvds;
302 bool supports_hdmi;
303 bool supports_dp;
304
Thierry Reding880cee02017-10-12 19:04:17 +0200305 const struct tegra_sor_regs *regs;
Thierry Redingc57997b2017-10-12 19:12:57 +0200306 bool has_nvdisplay;
Thierry Reding880cee02017-10-12 19:04:17 +0200307
Thierry Reding459cc2c2015-07-30 10:34:24 +0200308 const struct tegra_sor_hdmi_settings *settings;
309 unsigned int num_settings;
Thierry Reding30b49432015-08-03 15:50:32 +0200310
311 const u8 *xbar_cfg;
Thierry Reding459cc2c2015-07-30 10:34:24 +0200312};
313
314struct tegra_sor;
315
316struct tegra_sor_ops {
317 const char *name;
318 int (*probe)(struct tegra_sor *sor);
319 int (*remove)(struct tegra_sor *sor);
320};
321
Thierry Reding6b6b6042013-11-15 16:06:05 +0100322struct tegra_sor {
323 struct host1x_client client;
324 struct tegra_output output;
325 struct device *dev;
326
Thierry Reding459cc2c2015-07-30 10:34:24 +0200327 const struct tegra_sor_soc *soc;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100328 void __iomem *regs;
Thierry Redingc57997b2017-10-12 19:12:57 +0200329 unsigned int index;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100330
331 struct reset_control *rst;
332 struct clk *clk_parent;
333 struct clk *clk_safe;
Thierry Redinge1335e22017-10-12 17:53:11 +0200334 struct clk *clk_out;
335 struct clk *clk_pad;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100336 struct clk *clk_dp;
337 struct clk *clk;
338
Thierry Reding9542c232015-07-08 13:39:09 +0200339 struct drm_dp_aux *aux;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100340
Thierry Redingdab16332015-01-26 16:04:08 +0100341 struct drm_info_list *debugfs_files;
Thierry Reding459cc2c2015-07-30 10:34:24 +0200342
343 const struct tegra_sor_ops *ops;
Thierry Redingc57997b2017-10-12 19:12:57 +0200344 enum tegra_io_pad pad;
Thierry Reding459cc2c2015-07-30 10:34:24 +0200345
346 /* for HDMI 2.0 */
347 struct tegra_sor_hdmi_settings *settings;
348 unsigned int num_settings;
349
350 struct regulator *avdd_io_supply;
351 struct regulator *vdd_pll_supply;
352 struct regulator *hdmi_supply;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100353};
354
Thierry Redingc31efa72015-09-08 16:09:22 +0200355struct tegra_sor_state {
356 struct drm_connector_state base;
357
358 unsigned int bpc;
359};
360
361static inline struct tegra_sor_state *
362to_sor_state(struct drm_connector_state *state)
363{
364 return container_of(state, struct tegra_sor_state, base);
365}
366
Thierry Reding34fa1832014-06-05 16:31:10 +0200367struct tegra_sor_config {
368 u32 bits_per_pixel;
369
370 u32 active_polarity;
371 u32 active_count;
372 u32 tu_size;
373 u32 active_frac;
374 u32 watermark;
Thierry Reding7890b572014-06-05 16:12:46 +0200375
376 u32 hblank_symbols;
377 u32 vblank_symbols;
Thierry Reding34fa1832014-06-05 16:31:10 +0200378};
379
Thierry Reding6b6b6042013-11-15 16:06:05 +0100380static inline struct tegra_sor *
381host1x_client_to_sor(struct host1x_client *client)
382{
383 return container_of(client, struct tegra_sor, client);
384}
385
386static inline struct tegra_sor *to_sor(struct tegra_output *output)
387{
388 return container_of(output, struct tegra_sor, output);
389}
390
Thierry Reding5c5f1302017-08-15 15:41:09 +0200391static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned int offset)
Thierry Reding6b6b6042013-11-15 16:06:05 +0100392{
Thierry Reding932f6522017-08-15 15:41:14 +0200393 u32 value = readl(sor->regs + (offset << 2));
394
395 trace_sor_readl(sor->dev, offset, value);
396
397 return value;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100398}
399
Thierry Reding28fe2072015-01-26 16:02:48 +0100400static inline void tegra_sor_writel(struct tegra_sor *sor, u32 value,
Thierry Reding5c5f1302017-08-15 15:41:09 +0200401 unsigned int offset)
Thierry Reding6b6b6042013-11-15 16:06:05 +0100402{
Thierry Reding932f6522017-08-15 15:41:14 +0200403 trace_sor_writel(sor->dev, offset, value);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100404 writel(value, sor->regs + (offset << 2));
405}
406
Thierry Reding25bb2ce2015-08-03 14:23:29 +0200407static int tegra_sor_set_parent_clock(struct tegra_sor *sor, struct clk *parent)
408{
409 int err;
410
411 clk_disable_unprepare(sor->clk);
412
Thierry Redinge1335e22017-10-12 17:53:11 +0200413 err = clk_set_parent(sor->clk_out, parent);
Thierry Reding25bb2ce2015-08-03 14:23:29 +0200414 if (err < 0)
415 return err;
416
417 err = clk_prepare_enable(sor->clk);
418 if (err < 0)
419 return err;
420
421 return 0;
422}
423
Thierry Redinge1335e22017-10-12 17:53:11 +0200424struct tegra_clk_sor_pad {
Thierry Redingb2992212015-10-01 14:25:03 +0200425 struct clk_hw hw;
426 struct tegra_sor *sor;
427};
428
Thierry Redinge1335e22017-10-12 17:53:11 +0200429static inline struct tegra_clk_sor_pad *to_pad(struct clk_hw *hw)
Thierry Redingb2992212015-10-01 14:25:03 +0200430{
Thierry Redinge1335e22017-10-12 17:53:11 +0200431 return container_of(hw, struct tegra_clk_sor_pad, hw);
Thierry Redingb2992212015-10-01 14:25:03 +0200432}
433
Thierry Redinge1335e22017-10-12 17:53:11 +0200434static const char * const tegra_clk_sor_pad_parents[] = {
Thierry Redingb2992212015-10-01 14:25:03 +0200435 "pll_d2_out0", "pll_dp"
436};
437
Thierry Redinge1335e22017-10-12 17:53:11 +0200438static int tegra_clk_sor_pad_set_parent(struct clk_hw *hw, u8 index)
Thierry Redingb2992212015-10-01 14:25:03 +0200439{
Thierry Redinge1335e22017-10-12 17:53:11 +0200440 struct tegra_clk_sor_pad *pad = to_pad(hw);
441 struct tegra_sor *sor = pad->sor;
Thierry Redingb2992212015-10-01 14:25:03 +0200442 u32 value;
443
444 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
445 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
446
447 switch (index) {
448 case 0:
449 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK;
450 break;
451
452 case 1:
453 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
454 break;
455 }
456
457 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
458
459 return 0;
460}
461
Thierry Redinge1335e22017-10-12 17:53:11 +0200462static u8 tegra_clk_sor_pad_get_parent(struct clk_hw *hw)
Thierry Redingb2992212015-10-01 14:25:03 +0200463{
Thierry Redinge1335e22017-10-12 17:53:11 +0200464 struct tegra_clk_sor_pad *pad = to_pad(hw);
465 struct tegra_sor *sor = pad->sor;
Thierry Redingb2992212015-10-01 14:25:03 +0200466 u8 parent = U8_MAX;
467 u32 value;
468
469 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
470
471 switch (value & SOR_CLK_CNTRL_DP_CLK_SEL_MASK) {
472 case SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK:
473 case SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_PCLK:
474 parent = 0;
475 break;
476
477 case SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK:
478 case SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_DPCLK:
479 parent = 1;
480 break;
481 }
482
483 return parent;
484}
485
Thierry Redinge1335e22017-10-12 17:53:11 +0200486static const struct clk_ops tegra_clk_sor_pad_ops = {
487 .set_parent = tegra_clk_sor_pad_set_parent,
488 .get_parent = tegra_clk_sor_pad_get_parent,
Thierry Redingb2992212015-10-01 14:25:03 +0200489};
490
Thierry Redinge1335e22017-10-12 17:53:11 +0200491static struct clk *tegra_clk_sor_pad_register(struct tegra_sor *sor,
492 const char *name)
Thierry Redingb2992212015-10-01 14:25:03 +0200493{
Thierry Redinge1335e22017-10-12 17:53:11 +0200494 struct tegra_clk_sor_pad *pad;
Thierry Redingb2992212015-10-01 14:25:03 +0200495 struct clk_init_data init;
496 struct clk *clk;
497
Thierry Redinge1335e22017-10-12 17:53:11 +0200498 pad = devm_kzalloc(sor->dev, sizeof(*pad), GFP_KERNEL);
499 if (!pad)
Thierry Redingb2992212015-10-01 14:25:03 +0200500 return ERR_PTR(-ENOMEM);
501
Thierry Redinge1335e22017-10-12 17:53:11 +0200502 pad->sor = sor;
Thierry Redingb2992212015-10-01 14:25:03 +0200503
504 init.name = name;
505 init.flags = 0;
Thierry Redinge1335e22017-10-12 17:53:11 +0200506 init.parent_names = tegra_clk_sor_pad_parents;
507 init.num_parents = ARRAY_SIZE(tegra_clk_sor_pad_parents);
508 init.ops = &tegra_clk_sor_pad_ops;
Thierry Redingb2992212015-10-01 14:25:03 +0200509
Thierry Redinge1335e22017-10-12 17:53:11 +0200510 pad->hw.init = &init;
Thierry Redingb2992212015-10-01 14:25:03 +0200511
Thierry Redinge1335e22017-10-12 17:53:11 +0200512 clk = devm_clk_register(sor->dev, &pad->hw);
Thierry Redingb2992212015-10-01 14:25:03 +0200513
514 return clk;
515}
516
Thierry Reding6b6b6042013-11-15 16:06:05 +0100517static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
518 struct drm_dp_link *link)
519{
Thierry Reding6b6b6042013-11-15 16:06:05 +0100520 unsigned int i;
521 u8 pattern;
Thierry Reding28fe2072015-01-26 16:02:48 +0100522 u32 value;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100523 int err;
524
525 /* setup lane parameters */
526 value = SOR_LANE_DRIVE_CURRENT_LANE3(0x40) |
527 SOR_LANE_DRIVE_CURRENT_LANE2(0x40) |
528 SOR_LANE_DRIVE_CURRENT_LANE1(0x40) |
529 SOR_LANE_DRIVE_CURRENT_LANE0(0x40);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200530 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100531
532 value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) |
533 SOR_LANE_PREEMPHASIS_LANE2(0x0f) |
534 SOR_LANE_PREEMPHASIS_LANE1(0x0f) |
535 SOR_LANE_PREEMPHASIS_LANE0(0x0f);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200536 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100537
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200538 value = SOR_LANE_POSTCURSOR_LANE3(0x00) |
539 SOR_LANE_POSTCURSOR_LANE2(0x00) |
540 SOR_LANE_POSTCURSOR_LANE1(0x00) |
541 SOR_LANE_POSTCURSOR_LANE0(0x00);
542 tegra_sor_writel(sor, value, SOR_LANE_POSTCURSOR0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100543
544 /* disable LVDS mode */
545 tegra_sor_writel(sor, 0, SOR_LVDS);
546
Thierry Reding880cee02017-10-12 19:04:17 +0200547 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100548 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
549 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
550 value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */
Thierry Reding880cee02017-10-12 19:04:17 +0200551 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100552
Thierry Reding880cee02017-10-12 19:04:17 +0200553 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100554 value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
555 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0;
Thierry Reding880cee02017-10-12 19:04:17 +0200556 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100557
558 usleep_range(10, 100);
559
Thierry Reding880cee02017-10-12 19:04:17 +0200560 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100561 value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
562 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
Thierry Reding880cee02017-10-12 19:04:17 +0200563 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100564
Thierry Reding9542c232015-07-08 13:39:09 +0200565 err = drm_dp_aux_prepare(sor->aux, DP_SET_ANSI_8B10B);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100566 if (err < 0)
567 return err;
568
569 for (i = 0, value = 0; i < link->num_lanes; i++) {
570 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
571 SOR_DP_TPG_SCRAMBLER_NONE |
572 SOR_DP_TPG_PATTERN_TRAIN1;
573 value = (value << 8) | lane;
574 }
575
576 tegra_sor_writel(sor, value, SOR_DP_TPG);
577
578 pattern = DP_TRAINING_PATTERN_1;
579
Thierry Reding9542c232015-07-08 13:39:09 +0200580 err = drm_dp_aux_train(sor->aux, link, pattern);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100581 if (err < 0)
582 return err;
583
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200584 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100585 value |= SOR_DP_SPARE_SEQ_ENABLE;
586 value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
587 value |= SOR_DP_SPARE_MACRO_SOR_CLK;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200588 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100589
590 for (i = 0, value = 0; i < link->num_lanes; i++) {
591 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
592 SOR_DP_TPG_SCRAMBLER_NONE |
593 SOR_DP_TPG_PATTERN_TRAIN2;
594 value = (value << 8) | lane;
595 }
596
597 tegra_sor_writel(sor, value, SOR_DP_TPG);
598
599 pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2;
600
Thierry Reding9542c232015-07-08 13:39:09 +0200601 err = drm_dp_aux_train(sor->aux, link, pattern);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100602 if (err < 0)
603 return err;
604
605 for (i = 0, value = 0; i < link->num_lanes; i++) {
606 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
607 SOR_DP_TPG_SCRAMBLER_GALIOS |
608 SOR_DP_TPG_PATTERN_NONE;
609 value = (value << 8) | lane;
610 }
611
612 tegra_sor_writel(sor, value, SOR_DP_TPG);
613
614 pattern = DP_TRAINING_PATTERN_DISABLE;
615
Thierry Reding9542c232015-07-08 13:39:09 +0200616 err = drm_dp_aux_train(sor->aux, link, pattern);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100617 if (err < 0)
618 return err;
619
620 return 0;
621}
622
623static void tegra_sor_super_update(struct tegra_sor *sor)
624{
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200625 tegra_sor_writel(sor, 0, SOR_SUPER_STATE0);
626 tegra_sor_writel(sor, 1, SOR_SUPER_STATE0);
627 tegra_sor_writel(sor, 0, SOR_SUPER_STATE0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100628}
629
630static void tegra_sor_update(struct tegra_sor *sor)
631{
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200632 tegra_sor_writel(sor, 0, SOR_STATE0);
633 tegra_sor_writel(sor, 1, SOR_STATE0);
634 tegra_sor_writel(sor, 0, SOR_STATE0);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100635}
636
637static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout)
638{
Thierry Reding28fe2072015-01-26 16:02:48 +0100639 u32 value;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100640
641 value = tegra_sor_readl(sor, SOR_PWM_DIV);
642 value &= ~SOR_PWM_DIV_MASK;
643 value |= 0x400; /* period */
644 tegra_sor_writel(sor, value, SOR_PWM_DIV);
645
646 value = tegra_sor_readl(sor, SOR_PWM_CTL);
647 value &= ~SOR_PWM_CTL_DUTY_CYCLE_MASK;
648 value |= 0x400; /* duty cycle */
649 value &= ~SOR_PWM_CTL_CLK_SEL; /* clock source: PCLK */
650 value |= SOR_PWM_CTL_TRIGGER;
651 tegra_sor_writel(sor, value, SOR_PWM_CTL);
652
653 timeout = jiffies + msecs_to_jiffies(timeout);
654
655 while (time_before(jiffies, timeout)) {
656 value = tegra_sor_readl(sor, SOR_PWM_CTL);
657 if ((value & SOR_PWM_CTL_TRIGGER) == 0)
658 return 0;
659
660 usleep_range(25, 100);
661 }
662
663 return -ETIMEDOUT;
664}
665
666static int tegra_sor_attach(struct tegra_sor *sor)
667{
668 unsigned long value, timeout;
669
670 /* wake up in normal mode */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200671 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100672 value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE;
673 value |= SOR_SUPER_STATE_MODE_NORMAL;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200674 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100675 tegra_sor_super_update(sor);
676
677 /* attach */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200678 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100679 value |= SOR_SUPER_STATE_ATTACHED;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +0200680 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6b6b6042013-11-15 16:06:05 +0100681 tegra_sor_super_update(sor);
682
683 timeout = jiffies + msecs_to_jiffies(250);
684
685 while (time_before(jiffies, timeout)) {
686 value = tegra_sor_readl(sor, SOR_TEST);
687 if ((value & SOR_TEST_ATTACHED) != 0)
688 return 0;
689
690 usleep_range(25, 100);
691 }
692
693 return -ETIMEDOUT;
694}
695
696static int tegra_sor_wakeup(struct tegra_sor *sor)
697{
Thierry Reding6b6b6042013-11-15 16:06:05 +0100698 unsigned long value, timeout;
699
Thierry Reding6b6b6042013-11-15 16:06:05 +0100700 timeout = jiffies + msecs_to_jiffies(250);
701
702 /* wait for head to wake up */
703 while (time_before(jiffies, timeout)) {
704 value = tegra_sor_readl(sor, SOR_TEST);
705 value &= SOR_TEST_HEAD_MODE_MASK;
706
707 if (value == SOR_TEST_HEAD_MODE_AWAKE)
708 return 0;
709
710 usleep_range(25, 100);
711 }
712
713 return -ETIMEDOUT;
714}
715
716static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
717{
Thierry Reding28fe2072015-01-26 16:02:48 +0100718 u32 value;
Thierry Reding6b6b6042013-11-15 16:06:05 +0100719
720 value = tegra_sor_readl(sor, SOR_PWR);
721 value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU;
722 tegra_sor_writel(sor, value, SOR_PWR);
723
724 timeout = jiffies + msecs_to_jiffies(timeout);
725
726 while (time_before(jiffies, timeout)) {
727 value = tegra_sor_readl(sor, SOR_PWR);
728 if ((value & SOR_PWR_TRIGGER) == 0)
729 return 0;
730
731 usleep_range(25, 100);
732 }
733
734 return -ETIMEDOUT;
735}
736
Thierry Reding34fa1832014-06-05 16:31:10 +0200737struct tegra_sor_params {
738 /* number of link clocks per line */
739 unsigned int num_clocks;
740 /* ratio between input and output */
741 u64 ratio;
742 /* precision factor */
743 u64 precision;
744
745 unsigned int active_polarity;
746 unsigned int active_count;
747 unsigned int active_frac;
748 unsigned int tu_size;
749 unsigned int error;
750};
751
752static int tegra_sor_compute_params(struct tegra_sor *sor,
753 struct tegra_sor_params *params,
754 unsigned int tu_size)
755{
756 u64 active_sym, active_count, frac, approx;
757 u32 active_polarity, active_frac = 0;
758 const u64 f = params->precision;
759 s64 error;
760
761 active_sym = params->ratio * tu_size;
762 active_count = div_u64(active_sym, f) * f;
763 frac = active_sym - active_count;
764
765 /* fraction < 0.5 */
766 if (frac >= (f / 2)) {
767 active_polarity = 1;
768 frac = f - frac;
769 } else {
770 active_polarity = 0;
771 }
772
773 if (frac != 0) {
774 frac = div_u64(f * f, frac); /* 1/fraction */
775 if (frac <= (15 * f)) {
776 active_frac = div_u64(frac, f);
777
778 /* round up */
779 if (active_polarity)
780 active_frac++;
781 } else {
782 active_frac = active_polarity ? 1 : 15;
783 }
784 }
785
786 if (active_frac == 1)
787 active_polarity = 0;
788
789 if (active_polarity == 1) {
790 if (active_frac) {
791 approx = active_count + (active_frac * (f - 1)) * f;
792 approx = div_u64(approx, active_frac * f);
793 } else {
794 approx = active_count + f;
795 }
796 } else {
797 if (active_frac)
798 approx = active_count + div_u64(f, active_frac);
799 else
800 approx = active_count;
801 }
802
803 error = div_s64(active_sym - approx, tu_size);
804 error *= params->num_clocks;
805
Andrew Morton79211c82015-11-09 14:58:13 -0800806 if (error <= 0 && abs(error) < params->error) {
Thierry Reding34fa1832014-06-05 16:31:10 +0200807 params->active_count = div_u64(active_count, f);
808 params->active_polarity = active_polarity;
809 params->active_frac = active_frac;
Andrew Morton79211c82015-11-09 14:58:13 -0800810 params->error = abs(error);
Thierry Reding34fa1832014-06-05 16:31:10 +0200811 params->tu_size = tu_size;
812
813 if (error == 0)
814 return true;
815 }
816
817 return false;
818}
819
Thierry Redinga1983592015-07-21 16:46:52 +0200820static int tegra_sor_compute_config(struct tegra_sor *sor,
821 const struct drm_display_mode *mode,
822 struct tegra_sor_config *config,
823 struct drm_dp_link *link)
Thierry Reding34fa1832014-06-05 16:31:10 +0200824{
825 const u64 f = 100000, link_rate = link->rate * 1000;
826 const u64 pclk = mode->clock * 1000;
Thierry Reding7890b572014-06-05 16:12:46 +0200827 u64 input, output, watermark, num;
Thierry Reding34fa1832014-06-05 16:31:10 +0200828 struct tegra_sor_params params;
Thierry Reding34fa1832014-06-05 16:31:10 +0200829 u32 num_syms_per_line;
830 unsigned int i;
831
832 if (!link_rate || !link->num_lanes || !pclk || !config->bits_per_pixel)
833 return -EINVAL;
834
835 output = link_rate * 8 * link->num_lanes;
836 input = pclk * config->bits_per_pixel;
837
838 if (input >= output)
839 return -ERANGE;
840
841 memset(&params, 0, sizeof(params));
842 params.ratio = div64_u64(input * f, output);
843 params.num_clocks = div_u64(link_rate * mode->hdisplay, pclk);
844 params.precision = f;
845 params.error = 64 * f;
846 params.tu_size = 64;
847
848 for (i = params.tu_size; i >= 32; i--)
849 if (tegra_sor_compute_params(sor, &params, i))
850 break;
851
852 if (params.active_frac == 0) {
853 config->active_polarity = 0;
854 config->active_count = params.active_count;
855
856 if (!params.active_polarity)
857 config->active_count--;
858
859 config->tu_size = params.tu_size;
860 config->active_frac = 1;
861 } else {
862 config->active_polarity = params.active_polarity;
863 config->active_count = params.active_count;
864 config->active_frac = params.active_frac;
865 config->tu_size = params.tu_size;
866 }
867
868 dev_dbg(sor->dev,
869 "polarity: %d active count: %d tu size: %d active frac: %d\n",
870 config->active_polarity, config->active_count,
871 config->tu_size, config->active_frac);
872
873 watermark = params.ratio * config->tu_size * (f - params.ratio);
874 watermark = div_u64(watermark, f);
875
876 watermark = div_u64(watermark + params.error, f);
877 config->watermark = watermark + (config->bits_per_pixel / 8) + 2;
878 num_syms_per_line = (mode->hdisplay * config->bits_per_pixel) *
879 (link->num_lanes * 8);
880
881 if (config->watermark > 30) {
882 config->watermark = 30;
883 dev_err(sor->dev,
884 "unable to compute TU size, forcing watermark to %u\n",
885 config->watermark);
886 } else if (config->watermark > num_syms_per_line) {
887 config->watermark = num_syms_per_line;
888 dev_err(sor->dev, "watermark too high, forcing to %u\n",
889 config->watermark);
890 }
891
Thierry Reding7890b572014-06-05 16:12:46 +0200892 /* compute the number of symbols per horizontal blanking interval */
893 num = ((mode->htotal - mode->hdisplay) - 7) * link_rate;
894 config->hblank_symbols = div_u64(num, pclk);
895
896 if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
897 config->hblank_symbols -= 3;
898
899 config->hblank_symbols -= 12 / link->num_lanes;
900
901 /* compute the number of symbols per vertical blanking interval */
902 num = (mode->hdisplay - 25) * link_rate;
903 config->vblank_symbols = div_u64(num, pclk);
904 config->vblank_symbols -= 36 / link->num_lanes + 4;
905
906 dev_dbg(sor->dev, "blank symbols: H:%u V:%u\n", config->hblank_symbols,
907 config->vblank_symbols);
908
Thierry Reding34fa1832014-06-05 16:31:10 +0200909 return 0;
910}
911
Thierry Reding402f6bc2015-07-21 16:48:19 +0200912static void tegra_sor_apply_config(struct tegra_sor *sor,
913 const struct tegra_sor_config *config)
914{
915 u32 value;
916
917 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
918 value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
919 value |= SOR_DP_LINKCTL_TU_SIZE(config->tu_size);
920 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
921
922 value = tegra_sor_readl(sor, SOR_DP_CONFIG0);
923 value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
924 value |= SOR_DP_CONFIG_WATERMARK(config->watermark);
925
926 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
927 value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(config->active_count);
928
929 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
930 value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(config->active_frac);
931
932 if (config->active_polarity)
933 value |= SOR_DP_CONFIG_ACTIVE_SYM_POLARITY;
934 else
935 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY;
936
937 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
938 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE;
939 tegra_sor_writel(sor, value, SOR_DP_CONFIG0);
940
941 value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS);
942 value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK;
943 value |= config->hblank_symbols & 0xffff;
944 tegra_sor_writel(sor, value, SOR_DP_AUDIO_HBLANK_SYMBOLS);
945
946 value = tegra_sor_readl(sor, SOR_DP_AUDIO_VBLANK_SYMBOLS);
947 value &= ~SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK;
948 value |= config->vblank_symbols & 0xffff;
949 tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
950}
951
Thierry Reding2bd1dd32015-08-03 15:46:15 +0200952static void tegra_sor_mode_set(struct tegra_sor *sor,
953 const struct drm_display_mode *mode,
Thierry Redingc31efa72015-09-08 16:09:22 +0200954 struct tegra_sor_state *state)
Thierry Reding2bd1dd32015-08-03 15:46:15 +0200955{
956 struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc);
957 unsigned int vbe, vse, hbe, hse, vbs, hbs;
958 u32 value;
959
960 value = tegra_sor_readl(sor, SOR_STATE1);
961 value &= ~SOR_STATE_ASY_PIXELDEPTH_MASK;
962 value &= ~SOR_STATE_ASY_CRC_MODE_MASK;
963 value &= ~SOR_STATE_ASY_OWNER_MASK;
964
965 value |= SOR_STATE_ASY_CRC_MODE_COMPLETE |
966 SOR_STATE_ASY_OWNER(dc->pipe + 1);
967
968 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
969 value &= ~SOR_STATE_ASY_HSYNCPOL;
970
971 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
972 value |= SOR_STATE_ASY_HSYNCPOL;
973
974 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
975 value &= ~SOR_STATE_ASY_VSYNCPOL;
976
977 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
978 value |= SOR_STATE_ASY_VSYNCPOL;
979
Thierry Redingc31efa72015-09-08 16:09:22 +0200980 switch (state->bpc) {
981 case 16:
982 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_48_444;
983 break;
984
985 case 12:
986 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_36_444;
987 break;
988
989 case 10:
990 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_30_444;
991 break;
992
Thierry Reding2bd1dd32015-08-03 15:46:15 +0200993 case 8:
994 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
995 break;
996
997 case 6:
998 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444;
999 break;
1000
1001 default:
Thierry Redingc31efa72015-09-08 16:09:22 +02001002 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001003 break;
1004 }
1005
1006 tegra_sor_writel(sor, value, SOR_STATE1);
1007
1008 /*
1009 * TODO: The video timing programming below doesn't seem to match the
1010 * register definitions.
1011 */
1012
1013 value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
Thierry Reding880cee02017-10-12 19:04:17 +02001014 tegra_sor_writel(sor, value, sor->soc->regs->head_state1 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001015
1016 /* sync end = sync width - 1 */
1017 vse = mode->vsync_end - mode->vsync_start - 1;
1018 hse = mode->hsync_end - mode->hsync_start - 1;
1019
1020 value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
Thierry Reding880cee02017-10-12 19:04:17 +02001021 tegra_sor_writel(sor, value, sor->soc->regs->head_state2 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001022
1023 /* blank end = sync end + back porch */
1024 vbe = vse + (mode->vtotal - mode->vsync_end);
1025 hbe = hse + (mode->htotal - mode->hsync_end);
1026
1027 value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
Thierry Reding880cee02017-10-12 19:04:17 +02001028 tegra_sor_writel(sor, value, sor->soc->regs->head_state3 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001029
1030 /* blank start = blank end + active */
1031 vbs = vbe + mode->vdisplay;
1032 hbs = hbe + mode->hdisplay;
1033
1034 value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
Thierry Reding880cee02017-10-12 19:04:17 +02001035 tegra_sor_writel(sor, value, sor->soc->regs->head_state4 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001036
1037 /* XXX interlacing support */
Thierry Reding880cee02017-10-12 19:04:17 +02001038 tegra_sor_writel(sor, 0x001, sor->soc->regs->head_state5 + dc->pipe);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001039}
1040
Thierry Reding6fad8f62014-11-28 15:41:34 +01001041static int tegra_sor_detach(struct tegra_sor *sor)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001042{
Thierry Reding6fad8f62014-11-28 15:41:34 +01001043 unsigned long value, timeout;
1044
1045 /* switch to safe mode */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001046 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001047 value &= ~SOR_SUPER_STATE_MODE_NORMAL;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001048 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001049 tegra_sor_super_update(sor);
1050
1051 timeout = jiffies + msecs_to_jiffies(250);
1052
1053 while (time_before(jiffies, timeout)) {
1054 value = tegra_sor_readl(sor, SOR_PWR);
1055 if (value & SOR_PWR_MODE_SAFE)
1056 break;
1057 }
1058
1059 if ((value & SOR_PWR_MODE_SAFE) == 0)
1060 return -ETIMEDOUT;
1061
1062 /* go to sleep */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001063 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001064 value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001065 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001066 tegra_sor_super_update(sor);
1067
1068 /* detach */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001069 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001070 value &= ~SOR_SUPER_STATE_ATTACHED;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001071 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001072 tegra_sor_super_update(sor);
1073
1074 timeout = jiffies + msecs_to_jiffies(250);
1075
1076 while (time_before(jiffies, timeout)) {
1077 value = tegra_sor_readl(sor, SOR_TEST);
1078 if ((value & SOR_TEST_ATTACHED) == 0)
1079 break;
1080
1081 usleep_range(25, 100);
1082 }
1083
1084 if ((value & SOR_TEST_ATTACHED) != 0)
1085 return -ETIMEDOUT;
1086
1087 return 0;
1088}
1089
1090static int tegra_sor_power_down(struct tegra_sor *sor)
1091{
1092 unsigned long value, timeout;
1093 int err;
1094
1095 value = tegra_sor_readl(sor, SOR_PWR);
1096 value &= ~SOR_PWR_NORMAL_STATE_PU;
1097 value |= SOR_PWR_TRIGGER;
1098 tegra_sor_writel(sor, value, SOR_PWR);
1099
1100 timeout = jiffies + msecs_to_jiffies(250);
1101
1102 while (time_before(jiffies, timeout)) {
1103 value = tegra_sor_readl(sor, SOR_PWR);
1104 if ((value & SOR_PWR_TRIGGER) == 0)
1105 return 0;
1106
1107 usleep_range(25, 100);
1108 }
1109
1110 if ((value & SOR_PWR_TRIGGER) != 0)
1111 return -ETIMEDOUT;
1112
Thierry Reding25bb2ce2015-08-03 14:23:29 +02001113 /* switch to safe parent clock */
1114 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
Thierry Redinge1335e22017-10-12 17:53:11 +02001115 if (err < 0) {
Thierry Reding6fad8f62014-11-28 15:41:34 +01001116 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
Thierry Redinge1335e22017-10-12 17:53:11 +02001117 return err;
1118 }
Thierry Reding6fad8f62014-11-28 15:41:34 +01001119
Thierry Reding880cee02017-10-12 19:04:17 +02001120 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001121 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
1122 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2);
Thierry Reding880cee02017-10-12 19:04:17 +02001123 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001124
1125 /* stop lane sequencer */
1126 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP |
1127 SOR_LANE_SEQ_CTL_POWER_STATE_DOWN;
1128 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
1129
1130 timeout = jiffies + msecs_to_jiffies(250);
1131
1132 while (time_before(jiffies, timeout)) {
1133 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
1134 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
1135 break;
1136
1137 usleep_range(25, 100);
1138 }
1139
1140 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0)
1141 return -ETIMEDOUT;
1142
Thierry Reding880cee02017-10-12 19:04:17 +02001143 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001144 value |= SOR_PLL2_PORT_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001145 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001146
1147 usleep_range(20, 100);
1148
Thierry Reding880cee02017-10-12 19:04:17 +02001149 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001150 value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
Thierry Reding880cee02017-10-12 19:04:17 +02001151 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001152
Thierry Reding880cee02017-10-12 19:04:17 +02001153 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001154 value |= SOR_PLL2_SEQ_PLLCAPPD;
1155 value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
Thierry Reding880cee02017-10-12 19:04:17 +02001156 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001157
1158 usleep_range(20, 100);
1159
1160 return 0;
1161}
1162
Thierry Reding6fad8f62014-11-28 15:41:34 +01001163static int tegra_sor_crc_wait(struct tegra_sor *sor, unsigned long timeout)
1164{
1165 u32 value;
1166
1167 timeout = jiffies + msecs_to_jiffies(timeout);
1168
1169 while (time_before(jiffies, timeout)) {
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001170 value = tegra_sor_readl(sor, SOR_CRCA);
1171 if (value & SOR_CRCA_VALID)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001172 return 0;
1173
1174 usleep_range(100, 200);
1175 }
1176
1177 return -ETIMEDOUT;
1178}
1179
Thierry Reding530239a2015-08-06 11:04:54 +02001180static int tegra_sor_show_crc(struct seq_file *s, void *data)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001181{
Thierry Reding530239a2015-08-06 11:04:54 +02001182 struct drm_info_node *node = s->private;
1183 struct tegra_sor *sor = node->info_ent->data;
Thierry Reding850bab42015-07-29 17:58:41 +02001184 struct drm_crtc *crtc = sor->output.encoder.crtc;
1185 struct drm_device *drm = node->minor->dev;
Thierry Reding530239a2015-08-06 11:04:54 +02001186 int err = 0;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001187 u32 value;
1188
Thierry Reding850bab42015-07-29 17:58:41 +02001189 drm_modeset_lock_all(drm);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001190
Thierry Reding850bab42015-07-29 17:58:41 +02001191 if (!crtc || !crtc->state->active) {
1192 err = -EBUSY;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001193 goto unlock;
1194 }
1195
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001196 value = tegra_sor_readl(sor, SOR_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001197 value &= ~SOR_STATE_ASY_CRC_MODE_MASK;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001198 tegra_sor_writel(sor, value, SOR_STATE1);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001199
1200 value = tegra_sor_readl(sor, SOR_CRC_CNTRL);
1201 value |= SOR_CRC_CNTRL_ENABLE;
1202 tegra_sor_writel(sor, value, SOR_CRC_CNTRL);
1203
1204 value = tegra_sor_readl(sor, SOR_TEST);
1205 value &= ~SOR_TEST_CRC_POST_SERIALIZE;
1206 tegra_sor_writel(sor, value, SOR_TEST);
1207
1208 err = tegra_sor_crc_wait(sor, 100);
1209 if (err < 0)
1210 goto unlock;
1211
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001212 tegra_sor_writel(sor, SOR_CRCA_RESET, SOR_CRCA);
1213 value = tegra_sor_readl(sor, SOR_CRCB);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001214
Thierry Reding530239a2015-08-06 11:04:54 +02001215 seq_printf(s, "%08x\n", value);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001216
1217unlock:
Thierry Reding850bab42015-07-29 17:58:41 +02001218 drm_modeset_unlock_all(drm);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001219 return err;
1220}
1221
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001222#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
1223
1224static const struct debugfs_reg32 tegra_sor_regs[] = {
1225 DEBUGFS_REG32(SOR_CTXSW),
1226 DEBUGFS_REG32(SOR_SUPER_STATE0),
1227 DEBUGFS_REG32(SOR_SUPER_STATE1),
1228 DEBUGFS_REG32(SOR_STATE0),
1229 DEBUGFS_REG32(SOR_STATE1),
1230 DEBUGFS_REG32(SOR_HEAD_STATE0(0)),
1231 DEBUGFS_REG32(SOR_HEAD_STATE0(1)),
1232 DEBUGFS_REG32(SOR_HEAD_STATE1(0)),
1233 DEBUGFS_REG32(SOR_HEAD_STATE1(1)),
1234 DEBUGFS_REG32(SOR_HEAD_STATE2(0)),
1235 DEBUGFS_REG32(SOR_HEAD_STATE2(1)),
1236 DEBUGFS_REG32(SOR_HEAD_STATE3(0)),
1237 DEBUGFS_REG32(SOR_HEAD_STATE3(1)),
1238 DEBUGFS_REG32(SOR_HEAD_STATE4(0)),
1239 DEBUGFS_REG32(SOR_HEAD_STATE4(1)),
1240 DEBUGFS_REG32(SOR_HEAD_STATE5(0)),
1241 DEBUGFS_REG32(SOR_HEAD_STATE5(1)),
1242 DEBUGFS_REG32(SOR_CRC_CNTRL),
1243 DEBUGFS_REG32(SOR_DP_DEBUG_MVID),
1244 DEBUGFS_REG32(SOR_CLK_CNTRL),
1245 DEBUGFS_REG32(SOR_CAP),
1246 DEBUGFS_REG32(SOR_PWR),
1247 DEBUGFS_REG32(SOR_TEST),
1248 DEBUGFS_REG32(SOR_PLL0),
1249 DEBUGFS_REG32(SOR_PLL1),
1250 DEBUGFS_REG32(SOR_PLL2),
1251 DEBUGFS_REG32(SOR_PLL3),
1252 DEBUGFS_REG32(SOR_CSTM),
1253 DEBUGFS_REG32(SOR_LVDS),
1254 DEBUGFS_REG32(SOR_CRCA),
1255 DEBUGFS_REG32(SOR_CRCB),
1256 DEBUGFS_REG32(SOR_BLANK),
1257 DEBUGFS_REG32(SOR_SEQ_CTL),
1258 DEBUGFS_REG32(SOR_LANE_SEQ_CTL),
1259 DEBUGFS_REG32(SOR_SEQ_INST(0)),
1260 DEBUGFS_REG32(SOR_SEQ_INST(1)),
1261 DEBUGFS_REG32(SOR_SEQ_INST(2)),
1262 DEBUGFS_REG32(SOR_SEQ_INST(3)),
1263 DEBUGFS_REG32(SOR_SEQ_INST(4)),
1264 DEBUGFS_REG32(SOR_SEQ_INST(5)),
1265 DEBUGFS_REG32(SOR_SEQ_INST(6)),
1266 DEBUGFS_REG32(SOR_SEQ_INST(7)),
1267 DEBUGFS_REG32(SOR_SEQ_INST(8)),
1268 DEBUGFS_REG32(SOR_SEQ_INST(9)),
1269 DEBUGFS_REG32(SOR_SEQ_INST(10)),
1270 DEBUGFS_REG32(SOR_SEQ_INST(11)),
1271 DEBUGFS_REG32(SOR_SEQ_INST(12)),
1272 DEBUGFS_REG32(SOR_SEQ_INST(13)),
1273 DEBUGFS_REG32(SOR_SEQ_INST(14)),
1274 DEBUGFS_REG32(SOR_SEQ_INST(15)),
1275 DEBUGFS_REG32(SOR_PWM_DIV),
1276 DEBUGFS_REG32(SOR_PWM_CTL),
1277 DEBUGFS_REG32(SOR_VCRC_A0),
1278 DEBUGFS_REG32(SOR_VCRC_A1),
1279 DEBUGFS_REG32(SOR_VCRC_B0),
1280 DEBUGFS_REG32(SOR_VCRC_B1),
1281 DEBUGFS_REG32(SOR_CCRC_A0),
1282 DEBUGFS_REG32(SOR_CCRC_A1),
1283 DEBUGFS_REG32(SOR_CCRC_B0),
1284 DEBUGFS_REG32(SOR_CCRC_B1),
1285 DEBUGFS_REG32(SOR_EDATA_A0),
1286 DEBUGFS_REG32(SOR_EDATA_A1),
1287 DEBUGFS_REG32(SOR_EDATA_B0),
1288 DEBUGFS_REG32(SOR_EDATA_B1),
1289 DEBUGFS_REG32(SOR_COUNT_A0),
1290 DEBUGFS_REG32(SOR_COUNT_A1),
1291 DEBUGFS_REG32(SOR_COUNT_B0),
1292 DEBUGFS_REG32(SOR_COUNT_B1),
1293 DEBUGFS_REG32(SOR_DEBUG_A0),
1294 DEBUGFS_REG32(SOR_DEBUG_A1),
1295 DEBUGFS_REG32(SOR_DEBUG_B0),
1296 DEBUGFS_REG32(SOR_DEBUG_B1),
1297 DEBUGFS_REG32(SOR_TRIG),
1298 DEBUGFS_REG32(SOR_MSCHECK),
1299 DEBUGFS_REG32(SOR_XBAR_CTRL),
1300 DEBUGFS_REG32(SOR_XBAR_POL),
1301 DEBUGFS_REG32(SOR_DP_LINKCTL0),
1302 DEBUGFS_REG32(SOR_DP_LINKCTL1),
1303 DEBUGFS_REG32(SOR_LANE_DRIVE_CURRENT0),
1304 DEBUGFS_REG32(SOR_LANE_DRIVE_CURRENT1),
1305 DEBUGFS_REG32(SOR_LANE4_DRIVE_CURRENT0),
1306 DEBUGFS_REG32(SOR_LANE4_DRIVE_CURRENT1),
1307 DEBUGFS_REG32(SOR_LANE_PREEMPHASIS0),
1308 DEBUGFS_REG32(SOR_LANE_PREEMPHASIS1),
1309 DEBUGFS_REG32(SOR_LANE4_PREEMPHASIS0),
1310 DEBUGFS_REG32(SOR_LANE4_PREEMPHASIS1),
1311 DEBUGFS_REG32(SOR_LANE_POSTCURSOR0),
1312 DEBUGFS_REG32(SOR_LANE_POSTCURSOR1),
1313 DEBUGFS_REG32(SOR_DP_CONFIG0),
1314 DEBUGFS_REG32(SOR_DP_CONFIG1),
1315 DEBUGFS_REG32(SOR_DP_MN0),
1316 DEBUGFS_REG32(SOR_DP_MN1),
1317 DEBUGFS_REG32(SOR_DP_PADCTL0),
1318 DEBUGFS_REG32(SOR_DP_PADCTL1),
Thierry Redingc57997b2017-10-12 19:12:57 +02001319 DEBUGFS_REG32(SOR_DP_PADCTL2),
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001320 DEBUGFS_REG32(SOR_DP_DEBUG0),
1321 DEBUGFS_REG32(SOR_DP_DEBUG1),
1322 DEBUGFS_REG32(SOR_DP_SPARE0),
1323 DEBUGFS_REG32(SOR_DP_SPARE1),
1324 DEBUGFS_REG32(SOR_DP_AUDIO_CTRL),
1325 DEBUGFS_REG32(SOR_DP_AUDIO_HBLANK_SYMBOLS),
1326 DEBUGFS_REG32(SOR_DP_AUDIO_VBLANK_SYMBOLS),
1327 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_HEADER),
1328 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK0),
1329 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK1),
1330 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK2),
1331 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK3),
1332 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK4),
1333 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK5),
1334 DEBUGFS_REG32(SOR_DP_GENERIC_INFOFRAME_SUBPACK6),
1335 DEBUGFS_REG32(SOR_DP_TPG),
1336 DEBUGFS_REG32(SOR_DP_TPG_CONFIG),
1337 DEBUGFS_REG32(SOR_DP_LQ_CSTM0),
1338 DEBUGFS_REG32(SOR_DP_LQ_CSTM1),
1339 DEBUGFS_REG32(SOR_DP_LQ_CSTM2),
1340};
1341
Thierry Redingdab16332015-01-26 16:04:08 +01001342static int tegra_sor_show_regs(struct seq_file *s, void *data)
1343{
1344 struct drm_info_node *node = s->private;
1345 struct tegra_sor *sor = node->info_ent->data;
Thierry Reding850bab42015-07-29 17:58:41 +02001346 struct drm_crtc *crtc = sor->output.encoder.crtc;
1347 struct drm_device *drm = node->minor->dev;
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001348 unsigned int i;
Thierry Reding850bab42015-07-29 17:58:41 +02001349 int err = 0;
1350
1351 drm_modeset_lock_all(drm);
1352
1353 if (!crtc || !crtc->state->active) {
1354 err = -EBUSY;
1355 goto unlock;
1356 }
Thierry Redingdab16332015-01-26 16:04:08 +01001357
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001358 for (i = 0; i < ARRAY_SIZE(tegra_sor_regs); i++) {
1359 unsigned int offset = tegra_sor_regs[i].offset;
Thierry Redingdab16332015-01-26 16:04:08 +01001360
Thierry Reding062f5b2c2017-11-10 12:21:51 +01001361 seq_printf(s, "%-38s %#05x %08x\n", tegra_sor_regs[i].name,
1362 offset, tegra_sor_readl(sor, offset));
1363 }
Thierry Redingdab16332015-01-26 16:04:08 +01001364
Thierry Reding850bab42015-07-29 17:58:41 +02001365unlock:
1366 drm_modeset_unlock_all(drm);
1367 return err;
Thierry Redingdab16332015-01-26 16:04:08 +01001368}
1369
1370static const struct drm_info_list debugfs_files[] = {
Thierry Reding530239a2015-08-06 11:04:54 +02001371 { "crc", tegra_sor_show_crc, 0, NULL },
Thierry Redingdab16332015-01-26 16:04:08 +01001372 { "regs", tegra_sor_show_regs, 0, NULL },
1373};
1374
Thierry Reding5b8e0432017-11-08 13:20:01 +01001375static int tegra_sor_late_register(struct drm_connector *connector)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001376{
Thierry Reding5b8e0432017-11-08 13:20:01 +01001377 struct tegra_output *output = connector_to_output(connector);
1378 unsigned int i, count = ARRAY_SIZE(debugfs_files);
1379 struct drm_minor *minor = connector->dev->primary;
1380 struct dentry *root = connector->debugfs_entry;
1381 struct tegra_sor *sor = to_sor(output);
Thierry Reding530239a2015-08-06 11:04:54 +02001382 int err;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001383
Thierry Redingdab16332015-01-26 16:04:08 +01001384 sor->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1385 GFP_KERNEL);
Thierry Reding5b8e0432017-11-08 13:20:01 +01001386 if (!sor->debugfs_files)
1387 return -ENOMEM;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001388
Thierry Reding5b8e0432017-11-08 13:20:01 +01001389 for (i = 0; i < count; i++)
Thierry Redingdab16332015-01-26 16:04:08 +01001390 sor->debugfs_files[i].data = sor;
1391
Thierry Reding5b8e0432017-11-08 13:20:01 +01001392 err = drm_debugfs_create_files(sor->debugfs_files, count, root, minor);
Thierry Redingdab16332015-01-26 16:04:08 +01001393 if (err < 0)
1394 goto free;
1395
Thierry Reding530239a2015-08-06 11:04:54 +02001396 return 0;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001397
Thierry Redingdab16332015-01-26 16:04:08 +01001398free:
1399 kfree(sor->debugfs_files);
1400 sor->debugfs_files = NULL;
Thierry Reding5b8e0432017-11-08 13:20:01 +01001401
Thierry Reding6fad8f62014-11-28 15:41:34 +01001402 return err;
1403}
1404
Thierry Reding5b8e0432017-11-08 13:20:01 +01001405static void tegra_sor_early_unregister(struct drm_connector *connector)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001406{
Thierry Reding5b8e0432017-11-08 13:20:01 +01001407 struct tegra_output *output = connector_to_output(connector);
1408 unsigned int count = ARRAY_SIZE(debugfs_files);
1409 struct tegra_sor *sor = to_sor(output);
Thierry Redingd92e6002017-10-12 19:07:54 +02001410
Thierry Reding5b8e0432017-11-08 13:20:01 +01001411 drm_debugfs_remove_files(sor->debugfs_files, count,
1412 connector->dev->primary);
Thierry Redingdab16332015-01-26 16:04:08 +01001413 kfree(sor->debugfs_files);
Thierry Reding066d30f2015-07-03 14:16:30 +02001414 sor->debugfs_files = NULL;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001415}
1416
Thierry Redingc31efa72015-09-08 16:09:22 +02001417static void tegra_sor_connector_reset(struct drm_connector *connector)
1418{
1419 struct tegra_sor_state *state;
1420
1421 state = kzalloc(sizeof(*state), GFP_KERNEL);
1422 if (!state)
1423 return;
1424
1425 if (connector->state) {
1426 __drm_atomic_helper_connector_destroy_state(connector->state);
1427 kfree(connector->state);
1428 }
1429
1430 __drm_atomic_helper_connector_reset(connector, &state->base);
1431}
1432
Thierry Reding6fad8f62014-11-28 15:41:34 +01001433static enum drm_connector_status
1434tegra_sor_connector_detect(struct drm_connector *connector, bool force)
1435{
1436 struct tegra_output *output = connector_to_output(connector);
1437 struct tegra_sor *sor = to_sor(output);
1438
Thierry Reding9542c232015-07-08 13:39:09 +02001439 if (sor->aux)
1440 return drm_dp_aux_detect(sor->aux);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001441
Thierry Reding459cc2c2015-07-30 10:34:24 +02001442 return tegra_output_connector_detect(connector, force);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001443}
1444
Thierry Redingc31efa72015-09-08 16:09:22 +02001445static struct drm_connector_state *
1446tegra_sor_connector_duplicate_state(struct drm_connector *connector)
1447{
1448 struct tegra_sor_state *state = to_sor_state(connector->state);
1449 struct tegra_sor_state *copy;
1450
1451 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
1452 if (!copy)
1453 return NULL;
1454
1455 __drm_atomic_helper_connector_duplicate_state(connector, &copy->base);
1456
1457 return &copy->base;
1458}
1459
Thierry Reding6fad8f62014-11-28 15:41:34 +01001460static const struct drm_connector_funcs tegra_sor_connector_funcs = {
Thierry Redingc31efa72015-09-08 16:09:22 +02001461 .reset = tegra_sor_connector_reset,
Thierry Reding6fad8f62014-11-28 15:41:34 +01001462 .detect = tegra_sor_connector_detect,
1463 .fill_modes = drm_helper_probe_single_connector_modes,
1464 .destroy = tegra_output_connector_destroy,
Thierry Redingc31efa72015-09-08 16:09:22 +02001465 .atomic_duplicate_state = tegra_sor_connector_duplicate_state,
Thierry Reding4aa3df72014-11-24 16:27:13 +01001466 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
Thierry Reding5b8e0432017-11-08 13:20:01 +01001467 .late_register = tegra_sor_late_register,
1468 .early_unregister = tegra_sor_early_unregister,
Thierry Reding6fad8f62014-11-28 15:41:34 +01001469};
1470
1471static int tegra_sor_connector_get_modes(struct drm_connector *connector)
1472{
1473 struct tegra_output *output = connector_to_output(connector);
1474 struct tegra_sor *sor = to_sor(output);
1475 int err;
1476
Thierry Reding9542c232015-07-08 13:39:09 +02001477 if (sor->aux)
1478 drm_dp_aux_enable(sor->aux);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001479
1480 err = tegra_output_connector_get_modes(connector);
1481
Thierry Reding9542c232015-07-08 13:39:09 +02001482 if (sor->aux)
1483 drm_dp_aux_disable(sor->aux);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001484
1485 return err;
1486}
1487
1488static enum drm_mode_status
1489tegra_sor_connector_mode_valid(struct drm_connector *connector,
1490 struct drm_display_mode *mode)
1491{
Thierry Reding64ea25c2016-07-12 16:52:22 +02001492 /* HDMI 2.0 modes are not yet supported */
1493 if (mode->clock > 340000)
1494 return MODE_NOCLOCK;
1495
Thierry Reding6fad8f62014-11-28 15:41:34 +01001496 return MODE_OK;
1497}
1498
1499static const struct drm_connector_helper_funcs tegra_sor_connector_helper_funcs = {
1500 .get_modes = tegra_sor_connector_get_modes,
1501 .mode_valid = tegra_sor_connector_mode_valid,
Thierry Reding6fad8f62014-11-28 15:41:34 +01001502};
1503
1504static const struct drm_encoder_funcs tegra_sor_encoder_funcs = {
1505 .destroy = tegra_output_encoder_destroy,
1506};
1507
Thierry Reding850bab42015-07-29 17:58:41 +02001508static void tegra_sor_edp_disable(struct drm_encoder *encoder)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001509{
Thierry Reding850bab42015-07-29 17:58:41 +02001510 struct tegra_output *output = encoder_to_output(encoder);
1511 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
1512 struct tegra_sor *sor = to_sor(output);
1513 u32 value;
1514 int err;
1515
1516 if (output->panel)
1517 drm_panel_disable(output->panel);
1518
1519 err = tegra_sor_detach(sor);
1520 if (err < 0)
1521 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
1522
1523 tegra_sor_writel(sor, 0, SOR_STATE1);
1524 tegra_sor_update(sor);
1525
1526 /*
1527 * The following accesses registers of the display controller, so make
1528 * sure it's only executed when the output is attached to one.
1529 */
1530 if (dc) {
1531 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc57997b2017-10-12 19:12:57 +02001532 value &= ~SOR_ENABLE(0);
Thierry Reding850bab42015-07-29 17:58:41 +02001533 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
1534
1535 tegra_dc_commit(dc);
1536 }
1537
1538 err = tegra_sor_power_down(sor);
1539 if (err < 0)
1540 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
1541
Thierry Reding9542c232015-07-08 13:39:09 +02001542 if (sor->aux) {
1543 err = drm_dp_aux_disable(sor->aux);
Thierry Reding850bab42015-07-29 17:58:41 +02001544 if (err < 0)
1545 dev_err(sor->dev, "failed to disable DP: %d\n", err);
1546 }
1547
Thierry Redingc57997b2017-10-12 19:12:57 +02001548 err = tegra_io_pad_power_disable(sor->pad);
Thierry Reding850bab42015-07-29 17:58:41 +02001549 if (err < 0)
Thierry Redingc57997b2017-10-12 19:12:57 +02001550 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
Thierry Reding850bab42015-07-29 17:58:41 +02001551
1552 if (output->panel)
1553 drm_panel_unprepare(output->panel);
1554
Thierry Redingaaff8bd2015-08-07 16:04:54 +02001555 pm_runtime_put(sor->dev);
Thierry Reding6fad8f62014-11-28 15:41:34 +01001556}
1557
Thierry Reding459cc2c2015-07-30 10:34:24 +02001558#if 0
1559static int calc_h_ref_to_sync(const struct drm_display_mode *mode,
1560 unsigned int *value)
1561{
1562 unsigned int hfp, hsw, hbp, a = 0, b;
1563
1564 hfp = mode->hsync_start - mode->hdisplay;
1565 hsw = mode->hsync_end - mode->hsync_start;
1566 hbp = mode->htotal - mode->hsync_end;
1567
1568 pr_info("hfp: %u, hsw: %u, hbp: %u\n", hfp, hsw, hbp);
1569
1570 b = hfp - 1;
1571
1572 pr_info("a: %u, b: %u\n", a, b);
1573 pr_info("a + hsw + hbp = %u\n", a + hsw + hbp);
1574
1575 if (a + hsw + hbp <= 11) {
1576 a = 1 + 11 - hsw - hbp;
1577 pr_info("a: %u\n", a);
1578 }
1579
1580 if (a > b)
1581 return -EINVAL;
1582
1583 if (hsw < 1)
1584 return -EINVAL;
1585
1586 if (mode->hdisplay < 16)
1587 return -EINVAL;
1588
1589 if (value) {
1590 if (b > a && a % 2)
1591 *value = a + 1;
1592 else
1593 *value = a;
1594 }
1595
1596 return 0;
1597}
1598#endif
1599
Thierry Reding850bab42015-07-29 17:58:41 +02001600static void tegra_sor_edp_enable(struct drm_encoder *encoder)
Thierry Reding6fad8f62014-11-28 15:41:34 +01001601{
Thierry Reding850bab42015-07-29 17:58:41 +02001602 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
Thierry Reding6fad8f62014-11-28 15:41:34 +01001603 struct tegra_output *output = encoder_to_output(encoder);
1604 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001605 struct tegra_sor *sor = to_sor(output);
Thierry Reding34fa1832014-06-05 16:31:10 +02001606 struct tegra_sor_config config;
Thierry Redingc31efa72015-09-08 16:09:22 +02001607 struct tegra_sor_state *state;
Thierry Reding34fa1832014-06-05 16:31:10 +02001608 struct drm_dp_link link;
Thierry Reding01b9bea2015-11-11 17:15:29 +01001609 u8 rate, lanes;
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001610 unsigned int i;
Thierry Reding86f5c522014-03-26 11:13:16 +01001611 int err = 0;
Thierry Reding28fe2072015-01-26 16:02:48 +01001612 u32 value;
Thierry Reding86f5c522014-03-26 11:13:16 +01001613
Thierry Redingc31efa72015-09-08 16:09:22 +02001614 state = to_sor_state(output->connector.state);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001615
Thierry Redingaaff8bd2015-08-07 16:04:54 +02001616 pm_runtime_get_sync(sor->dev);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001617
Thierry Reding6fad8f62014-11-28 15:41:34 +01001618 if (output->panel)
1619 drm_panel_prepare(output->panel);
1620
Thierry Reding01b9bea2015-11-11 17:15:29 +01001621 err = drm_dp_aux_enable(sor->aux);
1622 if (err < 0)
1623 dev_err(sor->dev, "failed to enable DP: %d\n", err);
Thierry Reding34fa1832014-06-05 16:31:10 +02001624
Thierry Reding01b9bea2015-11-11 17:15:29 +01001625 err = drm_dp_link_probe(sor->aux, &link);
1626 if (err < 0) {
1627 dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
1628 return;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001629 }
1630
Thierry Reding25bb2ce2015-08-03 14:23:29 +02001631 /* switch to safe parent clock */
1632 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001633 if (err < 0)
1634 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
1635
Thierry Reding34fa1832014-06-05 16:31:10 +02001636 memset(&config, 0, sizeof(config));
Thierry Redingc31efa72015-09-08 16:09:22 +02001637 config.bits_per_pixel = state->bpc * 3;
Thierry Reding34fa1832014-06-05 16:31:10 +02001638
Thierry Redinga1983592015-07-21 16:46:52 +02001639 err = tegra_sor_compute_config(sor, mode, &config, &link);
Thierry Reding34fa1832014-06-05 16:31:10 +02001640 if (err < 0)
Thierry Redinga1983592015-07-21 16:46:52 +02001641 dev_err(sor->dev, "failed to compute configuration: %d\n", err);
Thierry Reding34fa1832014-06-05 16:31:10 +02001642
Thierry Reding6b6b6042013-11-15 16:06:05 +01001643 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1644 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
1645 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
1646 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1647
Thierry Reding880cee02017-10-12 19:04:17 +02001648 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001649 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001650 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001651 usleep_range(20, 100);
1652
Thierry Reding880cee02017-10-12 19:04:17 +02001653 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001654 value |= SOR_PLL3_PLL_VDD_MODE_3V3;
Thierry Reding880cee02017-10-12 19:04:17 +02001655 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001656
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001657 value = SOR_PLL0_ICHPMP(0xf) | SOR_PLL0_VCOCAP_RST |
1658 SOR_PLL0_PLLREG_LEVEL_V45 | SOR_PLL0_RESISTOR_EXT;
Thierry Reding880cee02017-10-12 19:04:17 +02001659 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001660
Thierry Reding880cee02017-10-12 19:04:17 +02001661 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001662 value |= SOR_PLL2_SEQ_PLLCAPPD;
1663 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
1664 value |= SOR_PLL2_LVDS_ENABLE;
Thierry Reding880cee02017-10-12 19:04:17 +02001665 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001666
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001667 value = SOR_PLL1_TERM_COMPOUT | SOR_PLL1_TMDS_TERM;
Thierry Reding880cee02017-10-12 19:04:17 +02001668 tegra_sor_writel(sor, value, sor->soc->regs->pll1);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001669
1670 while (true) {
Thierry Reding880cee02017-10-12 19:04:17 +02001671 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001672 if ((value & SOR_PLL2_SEQ_PLLCAPPD_ENFORCE) == 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001673 break;
1674
1675 usleep_range(250, 1000);
1676 }
1677
Thierry Reding880cee02017-10-12 19:04:17 +02001678 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001679 value &= ~SOR_PLL2_POWERDOWN_OVERRIDE;
1680 value &= ~SOR_PLL2_PORT_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001681 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001682
1683 /*
1684 * power up
1685 */
1686
1687 /* set safe link bandwidth (1.62 Gbps) */
1688 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1689 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
1690 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62;
1691 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1692
1693 /* step 1 */
Thierry Reding880cee02017-10-12 19:04:17 +02001694 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001695 value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL2_PORT_POWERDOWN |
1696 SOR_PLL2_BANDGAP_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001697 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001698
Thierry Reding880cee02017-10-12 19:04:17 +02001699 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001700 value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
Thierry Reding880cee02017-10-12 19:04:17 +02001701 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001702
Thierry Reding880cee02017-10-12 19:04:17 +02001703 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001704 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
Thierry Reding880cee02017-10-12 19:04:17 +02001705 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001706
1707 /* step 2 */
Thierry Redingc57997b2017-10-12 19:12:57 +02001708 err = tegra_io_pad_power_enable(sor->pad);
Thierry Reding850bab42015-07-29 17:58:41 +02001709 if (err < 0)
Thierry Redingc57997b2017-10-12 19:12:57 +02001710 dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001711
1712 usleep_range(5, 100);
1713
1714 /* step 3 */
Thierry Reding880cee02017-10-12 19:04:17 +02001715 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001716 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001717 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001718
1719 usleep_range(20, 100);
1720
1721 /* step 4 */
Thierry Reding880cee02017-10-12 19:04:17 +02001722 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001723 value &= ~SOR_PLL0_VCOPD;
1724 value &= ~SOR_PLL0_PWR;
Thierry Reding880cee02017-10-12 19:04:17 +02001725 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001726
Thierry Reding880cee02017-10-12 19:04:17 +02001727 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001728 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
Thierry Reding880cee02017-10-12 19:04:17 +02001729 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001730
1731 usleep_range(200, 1000);
1732
1733 /* step 5 */
Thierry Reding880cee02017-10-12 19:04:17 +02001734 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001735 value &= ~SOR_PLL2_PORT_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02001736 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001737
Thierry Reding30b49432015-08-03 15:50:32 +02001738 /* XXX not in TRM */
1739 for (value = 0, i = 0; i < 5; i++)
1740 value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->soc->xbar_cfg[i]) |
1741 SOR_XBAR_CTRL_LINK1_XSEL(i, i);
1742
1743 tegra_sor_writel(sor, 0x00000000, SOR_XBAR_POL);
1744 tegra_sor_writel(sor, value, SOR_XBAR_CTRL);
1745
Thierry Reding25bb2ce2015-08-03 14:23:29 +02001746 /* switch to DP parent clock */
1747 err = tegra_sor_set_parent_clock(sor, sor->clk_dp);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001748 if (err < 0)
Thierry Reding25bb2ce2015-08-03 14:23:29 +02001749 dev_err(sor->dev, "failed to set parent clock: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001750
Thierry Reding899451b2014-06-05 16:19:48 +02001751 /* power DP lanes */
Thierry Reding880cee02017-10-12 19:04:17 +02001752 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding899451b2014-06-05 16:19:48 +02001753
1754 if (link.num_lanes <= 2)
1755 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2);
1756 else
1757 value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2;
1758
1759 if (link.num_lanes <= 1)
1760 value &= ~SOR_DP_PADCTL_PD_TXD_1;
1761 else
1762 value |= SOR_DP_PADCTL_PD_TXD_1;
1763
1764 if (link.num_lanes == 0)
1765 value &= ~SOR_DP_PADCTL_PD_TXD_0;
1766 else
1767 value |= SOR_DP_PADCTL_PD_TXD_0;
1768
Thierry Reding880cee02017-10-12 19:04:17 +02001769 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001770
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001771 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001772 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
Thierry Reding0c90a182014-06-05 16:29:46 +02001773 value |= SOR_DP_LINKCTL_LANE_COUNT(link.num_lanes);
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001774 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001775
1776 /* start lane sequencer */
1777 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
1778 SOR_LANE_SEQ_CTL_POWER_STATE_UP;
1779 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
1780
1781 while (true) {
1782 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
1783 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
1784 break;
1785
1786 usleep_range(250, 1000);
1787 }
1788
Thierry Redinga4263fe2014-06-05 16:16:23 +02001789 /* set link bandwidth */
Thierry Reding6b6b6042013-11-15 16:06:05 +01001790 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1791 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
Thierry Redinga4263fe2014-06-05 16:16:23 +02001792 value |= drm_dp_link_rate_to_bw_code(link.rate) << 2;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001793 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1794
Thierry Reding402f6bc2015-07-21 16:48:19 +02001795 tegra_sor_apply_config(sor, &config);
1796
1797 /* enable link */
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001798 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001799 value |= SOR_DP_LINKCTL_ENABLE;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001800 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
Thierry Redinga9a9e4f2015-04-27 15:01:14 +02001801 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001802
1803 for (i = 0, value = 0; i < 4; i++) {
1804 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
1805 SOR_DP_TPG_SCRAMBLER_GALIOS |
1806 SOR_DP_TPG_PATTERN_NONE;
1807 value = (value << 8) | lane;
1808 }
1809
1810 tegra_sor_writel(sor, value, SOR_DP_TPG);
1811
Thierry Reding6b6b6042013-11-15 16:06:05 +01001812 /* enable pad calibration logic */
Thierry Reding880cee02017-10-12 19:04:17 +02001813 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001814 value |= SOR_DP_PADCTL_PAD_CAL_PD;
Thierry Reding880cee02017-10-12 19:04:17 +02001815 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001816
Thierry Reding01b9bea2015-11-11 17:15:29 +01001817 err = drm_dp_link_probe(sor->aux, &link);
1818 if (err < 0)
1819 dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001820
Thierry Reding01b9bea2015-11-11 17:15:29 +01001821 err = drm_dp_link_power_up(sor->aux, &link);
1822 if (err < 0)
1823 dev_err(sor->dev, "failed to power up eDP link: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001824
Thierry Reding01b9bea2015-11-11 17:15:29 +01001825 err = drm_dp_link_configure(sor->aux, &link);
1826 if (err < 0)
1827 dev_err(sor->dev, "failed to configure eDP link: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001828
Thierry Reding01b9bea2015-11-11 17:15:29 +01001829 rate = drm_dp_link_rate_to_bw_code(link.rate);
1830 lanes = link.num_lanes;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001831
Thierry Reding01b9bea2015-11-11 17:15:29 +01001832 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1833 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
1834 value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
1835 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001836
Thierry Reding01b9bea2015-11-11 17:15:29 +01001837 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
1838 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
1839 value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001840
Thierry Reding01b9bea2015-11-11 17:15:29 +01001841 if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
1842 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001843
Thierry Reding01b9bea2015-11-11 17:15:29 +01001844 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001845
Thierry Reding01b9bea2015-11-11 17:15:29 +01001846 /* disable training pattern generator */
Thierry Reding6b6b6042013-11-15 16:06:05 +01001847
Thierry Reding01b9bea2015-11-11 17:15:29 +01001848 for (i = 0; i < link.num_lanes; i++) {
1849 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
1850 SOR_DP_TPG_SCRAMBLER_GALIOS |
1851 SOR_DP_TPG_PATTERN_NONE;
1852 value = (value << 8) | lane;
Thierry Reding6b6b6042013-11-15 16:06:05 +01001853 }
1854
Thierry Reding01b9bea2015-11-11 17:15:29 +01001855 tegra_sor_writel(sor, value, SOR_DP_TPG);
1856
1857 err = tegra_sor_dp_train_fast(sor, &link);
1858 if (err < 0)
1859 dev_err(sor->dev, "DP fast link training failed: %d\n", err);
1860
1861 dev_dbg(sor->dev, "fast link training succeeded\n");
1862
Thierry Reding6b6b6042013-11-15 16:06:05 +01001863 err = tegra_sor_power_up(sor, 250);
Thierry Reding850bab42015-07-29 17:58:41 +02001864 if (err < 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001865 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001866
Thierry Reding6b6b6042013-11-15 16:06:05 +01001867 /* CSTM (LVDS, link A/B, upper) */
Stéphane Marchesin143b1df2014-05-22 20:32:47 -07001868 value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B |
Thierry Reding6b6b6042013-11-15 16:06:05 +01001869 SOR_CSTM_UPPER;
1870 tegra_sor_writel(sor, value, SOR_CSTM);
1871
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001872 /* use DP-A protocol */
1873 value = tegra_sor_readl(sor, SOR_STATE1);
1874 value &= ~SOR_STATE_ASY_PROTOCOL_MASK;
1875 value |= SOR_STATE_ASY_PROTOCOL_DP_A;
1876 tegra_sor_writel(sor, value, SOR_STATE1);
1877
Thierry Redingc31efa72015-09-08 16:09:22 +02001878 tegra_sor_mode_set(sor, mode, state);
Thierry Reding2bd1dd32015-08-03 15:46:15 +02001879
Thierry Reding6b6b6042013-11-15 16:06:05 +01001880 /* PWM setup */
1881 err = tegra_sor_setup_pwm(sor, 250);
Thierry Reding850bab42015-07-29 17:58:41 +02001882 if (err < 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001883 dev_err(sor->dev, "failed to setup PWM: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001884
Thierry Reding666cb872014-12-08 16:32:47 +01001885 tegra_sor_update(sor);
1886
Thierry Reding6b6b6042013-11-15 16:06:05 +01001887 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc57997b2017-10-12 19:12:57 +02001888 value |= SOR_ENABLE(0);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001889 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
1890
Thierry Reding666cb872014-12-08 16:32:47 +01001891 tegra_dc_commit(dc);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001892
1893 err = tegra_sor_attach(sor);
Thierry Reding850bab42015-07-29 17:58:41 +02001894 if (err < 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001895 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001896
1897 err = tegra_sor_wakeup(sor);
Thierry Reding850bab42015-07-29 17:58:41 +02001898 if (err < 0)
Thierry Reding6b6b6042013-11-15 16:06:05 +01001899 dev_err(sor->dev, "failed to enable DC: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001900
Thierry Reding6fad8f62014-11-28 15:41:34 +01001901 if (output->panel)
1902 drm_panel_enable(output->panel);
Thierry Reding6b6b6042013-11-15 16:06:05 +01001903}
1904
Thierry Reding82f15112014-12-08 17:26:46 +01001905static int
1906tegra_sor_encoder_atomic_check(struct drm_encoder *encoder,
1907 struct drm_crtc_state *crtc_state,
1908 struct drm_connector_state *conn_state)
1909{
1910 struct tegra_output *output = encoder_to_output(encoder);
Thierry Redingc31efa72015-09-08 16:09:22 +02001911 struct tegra_sor_state *state = to_sor_state(conn_state);
Thierry Reding82f15112014-12-08 17:26:46 +01001912 struct tegra_dc *dc = to_tegra_dc(conn_state->crtc);
1913 unsigned long pclk = crtc_state->mode.clock * 1000;
1914 struct tegra_sor *sor = to_sor(output);
Thierry Redingc31efa72015-09-08 16:09:22 +02001915 struct drm_display_info *info;
Thierry Reding82f15112014-12-08 17:26:46 +01001916 int err;
1917
Thierry Redingc31efa72015-09-08 16:09:22 +02001918 info = &output->connector.display_info;
1919
Thierry Reding82f15112014-12-08 17:26:46 +01001920 err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent,
1921 pclk, 0);
1922 if (err < 0) {
1923 dev_err(output->dev, "failed to setup CRTC state: %d\n", err);
1924 return err;
1925 }
1926
Thierry Redingc31efa72015-09-08 16:09:22 +02001927 switch (info->bpc) {
1928 case 8:
1929 case 6:
1930 state->bpc = info->bpc;
1931 break;
1932
1933 default:
1934 DRM_DEBUG_KMS("%u bits-per-color not supported\n", info->bpc);
1935 state->bpc = 8;
1936 break;
1937 }
1938
Thierry Reding82f15112014-12-08 17:26:46 +01001939 return 0;
1940}
1941
Thierry Reding459cc2c2015-07-30 10:34:24 +02001942static const struct drm_encoder_helper_funcs tegra_sor_edp_helpers = {
Thierry Reding850bab42015-07-29 17:58:41 +02001943 .disable = tegra_sor_edp_disable,
1944 .enable = tegra_sor_edp_enable,
Thierry Reding82f15112014-12-08 17:26:46 +01001945 .atomic_check = tegra_sor_encoder_atomic_check,
Thierry Reding6b6b6042013-11-15 16:06:05 +01001946};
1947
Thierry Reding459cc2c2015-07-30 10:34:24 +02001948static inline u32 tegra_sor_hdmi_subpack(const u8 *ptr, size_t size)
1949{
1950 u32 value = 0;
1951 size_t i;
1952
1953 for (i = size; i > 0; i--)
1954 value = (value << 8) | ptr[i - 1];
1955
1956 return value;
1957}
1958
1959static void tegra_sor_hdmi_write_infopack(struct tegra_sor *sor,
1960 const void *data, size_t size)
1961{
1962 const u8 *ptr = data;
1963 unsigned long offset;
1964 size_t i, j;
1965 u32 value;
1966
1967 switch (ptr[0]) {
1968 case HDMI_INFOFRAME_TYPE_AVI:
1969 offset = SOR_HDMI_AVI_INFOFRAME_HEADER;
1970 break;
1971
1972 case HDMI_INFOFRAME_TYPE_AUDIO:
1973 offset = SOR_HDMI_AUDIO_INFOFRAME_HEADER;
1974 break;
1975
1976 case HDMI_INFOFRAME_TYPE_VENDOR:
1977 offset = SOR_HDMI_VSI_INFOFRAME_HEADER;
1978 break;
1979
1980 default:
1981 dev_err(sor->dev, "unsupported infoframe type: %02x\n",
1982 ptr[0]);
1983 return;
1984 }
1985
1986 value = INFOFRAME_HEADER_TYPE(ptr[0]) |
1987 INFOFRAME_HEADER_VERSION(ptr[1]) |
1988 INFOFRAME_HEADER_LEN(ptr[2]);
1989 tegra_sor_writel(sor, value, offset);
1990 offset++;
1991
1992 /*
1993 * Each subpack contains 7 bytes, divided into:
1994 * - subpack_low: bytes 0 - 3
1995 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
1996 */
1997 for (i = 3, j = 0; i < size; i += 7, j += 8) {
1998 size_t rem = size - i, num = min_t(size_t, rem, 4);
1999
2000 value = tegra_sor_hdmi_subpack(&ptr[i], num);
2001 tegra_sor_writel(sor, value, offset++);
2002
2003 num = min_t(size_t, rem - num, 3);
2004
2005 value = tegra_sor_hdmi_subpack(&ptr[i + 4], num);
2006 tegra_sor_writel(sor, value, offset++);
2007 }
2008}
2009
2010static int
2011tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
2012 const struct drm_display_mode *mode)
2013{
2014 u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
2015 struct hdmi_avi_infoframe frame;
2016 u32 value;
2017 int err;
2018
2019 /* disable AVI infoframe */
2020 value = tegra_sor_readl(sor, SOR_HDMI_AVI_INFOFRAME_CTRL);
2021 value &= ~INFOFRAME_CTRL_SINGLE;
2022 value &= ~INFOFRAME_CTRL_OTHER;
2023 value &= ~INFOFRAME_CTRL_ENABLE;
2024 tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
2025
Shashank Sharma0c1f5282017-07-13 21:03:07 +05302026 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002027 if (err < 0) {
2028 dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
2029 return err;
2030 }
2031
2032 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
2033 if (err < 0) {
2034 dev_err(sor->dev, "failed to pack AVI infoframe: %d\n", err);
2035 return err;
2036 }
2037
2038 tegra_sor_hdmi_write_infopack(sor, buffer, err);
2039
2040 /* enable AVI infoframe */
2041 value = tegra_sor_readl(sor, SOR_HDMI_AVI_INFOFRAME_CTRL);
2042 value |= INFOFRAME_CTRL_CHECKSUM_ENABLE;
2043 value |= INFOFRAME_CTRL_ENABLE;
2044 tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
2045
2046 return 0;
2047}
2048
2049static void tegra_sor_hdmi_disable_audio_infoframe(struct tegra_sor *sor)
2050{
2051 u32 value;
2052
2053 value = tegra_sor_readl(sor, SOR_HDMI_AUDIO_INFOFRAME_CTRL);
2054 value &= ~INFOFRAME_CTRL_ENABLE;
2055 tegra_sor_writel(sor, value, SOR_HDMI_AUDIO_INFOFRAME_CTRL);
2056}
2057
2058static struct tegra_sor_hdmi_settings *
2059tegra_sor_hdmi_find_settings(struct tegra_sor *sor, unsigned long frequency)
2060{
2061 unsigned int i;
2062
2063 for (i = 0; i < sor->num_settings; i++)
2064 if (frequency <= sor->settings[i].frequency)
2065 return &sor->settings[i];
2066
2067 return NULL;
2068}
2069
2070static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
2071{
2072 struct tegra_output *output = encoder_to_output(encoder);
2073 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
2074 struct tegra_sor *sor = to_sor(output);
2075 u32 value;
2076 int err;
2077
2078 err = tegra_sor_detach(sor);
2079 if (err < 0)
2080 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
2081
2082 tegra_sor_writel(sor, 0, SOR_STATE1);
2083 tegra_sor_update(sor);
2084
2085 /* disable display to SOR clock */
2086 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc57997b2017-10-12 19:12:57 +02002087
2088 if (!sor->soc->has_nvdisplay)
2089 value &= ~(SOR1_TIMING_CYA | SOR_ENABLE(1));
2090 else
2091 value &= ~SOR_ENABLE(sor->index);
2092
Thierry Reding459cc2c2015-07-30 10:34:24 +02002093 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
2094
2095 tegra_dc_commit(dc);
2096
2097 err = tegra_sor_power_down(sor);
2098 if (err < 0)
2099 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
2100
Thierry Redingc57997b2017-10-12 19:12:57 +02002101 err = tegra_io_pad_power_disable(sor->pad);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002102 if (err < 0)
Thierry Redingc57997b2017-10-12 19:12:57 +02002103 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002104
Thierry Redingaaff8bd2015-08-07 16:04:54 +02002105 pm_runtime_put(sor->dev);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002106}
2107
2108static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2109{
2110 struct tegra_output *output = encoder_to_output(encoder);
2111 unsigned int h_ref_to_sync = 1, pulse_start, max_ac;
2112 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002113 struct tegra_sor_hdmi_settings *settings;
2114 struct tegra_sor *sor = to_sor(output);
Thierry Redingc31efa72015-09-08 16:09:22 +02002115 struct tegra_sor_state *state;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002116 struct drm_display_mode *mode;
Thierry Reding30b49432015-08-03 15:50:32 +02002117 unsigned int div, i;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002118 u32 value;
2119 int err;
2120
Thierry Redingc31efa72015-09-08 16:09:22 +02002121 state = to_sor_state(output->connector.state);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002122 mode = &encoder->crtc->state->adjusted_mode;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002123
Thierry Redingaaff8bd2015-08-07 16:04:54 +02002124 pm_runtime_get_sync(sor->dev);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002125
Thierry Reding25bb2ce2015-08-03 14:23:29 +02002126 /* switch to safe parent clock */
2127 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
Thierry Redinge1335e22017-10-12 17:53:11 +02002128 if (err < 0) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002129 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
Thierry Redinge1335e22017-10-12 17:53:11 +02002130 return;
2131 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002132
2133 div = clk_get_rate(sor->clk) / 1000000 * 4;
2134
Thierry Redingc57997b2017-10-12 19:12:57 +02002135 err = tegra_io_pad_power_enable(sor->pad);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002136 if (err < 0)
Thierry Redingc57997b2017-10-12 19:12:57 +02002137 dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002138
2139 usleep_range(20, 100);
2140
Thierry Reding880cee02017-10-12 19:04:17 +02002141 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002142 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02002143 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002144
2145 usleep_range(20, 100);
2146
Thierry Reding880cee02017-10-12 19:04:17 +02002147 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002148 value &= ~SOR_PLL3_PLL_VDD_MODE_3V3;
Thierry Reding880cee02017-10-12 19:04:17 +02002149 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002150
Thierry Reding880cee02017-10-12 19:04:17 +02002151 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002152 value &= ~SOR_PLL0_VCOPD;
2153 value &= ~SOR_PLL0_PWR;
Thierry Reding880cee02017-10-12 19:04:17 +02002154 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002155
Thierry Reding880cee02017-10-12 19:04:17 +02002156 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002157 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
Thierry Reding880cee02017-10-12 19:04:17 +02002158 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002159
2160 usleep_range(200, 400);
2161
Thierry Reding880cee02017-10-12 19:04:17 +02002162 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002163 value &= ~SOR_PLL2_POWERDOWN_OVERRIDE;
2164 value &= ~SOR_PLL2_PORT_POWERDOWN;
Thierry Reding880cee02017-10-12 19:04:17 +02002165 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002166
2167 usleep_range(20, 100);
2168
Thierry Reding880cee02017-10-12 19:04:17 +02002169 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002170 value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
2171 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2;
Thierry Reding880cee02017-10-12 19:04:17 +02002172 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002173
2174 while (true) {
2175 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
2176 if ((value & SOR_LANE_SEQ_CTL_STATE_BUSY) == 0)
2177 break;
2178
2179 usleep_range(250, 1000);
2180 }
2181
2182 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
2183 SOR_LANE_SEQ_CTL_POWER_STATE_UP | SOR_LANE_SEQ_CTL_DELAY(5);
2184 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
2185
2186 while (true) {
2187 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
2188 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
2189 break;
2190
2191 usleep_range(250, 1000);
2192 }
2193
2194 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
2195 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
2196 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
2197
2198 if (mode->clock < 340000)
2199 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70;
2200 else
2201 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40;
2202
2203 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK;
2204 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
2205
Thierry Redingc57997b2017-10-12 19:12:57 +02002206 /* SOR pad PLL stabilization time */
2207 usleep_range(250, 1000);
2208
2209 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
2210 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
2211 value |= SOR_DP_LINKCTL_LANE_COUNT(4);
2212 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
2213
Thierry Reding459cc2c2015-07-30 10:34:24 +02002214 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
Thierry Redingc57997b2017-10-12 19:12:57 +02002215 value &= ~SOR_DP_SPARE_DISP_VIDEO_PREAMBLE;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002216 value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
Thierry Redingc57997b2017-10-12 19:12:57 +02002217 value &= ~SOR_DP_SPARE_SEQ_ENABLE;
2218 value &= ~SOR_DP_SPARE_MACRO_SOR_CLK;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002219 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
2220
2221 value = SOR_SEQ_CTL_PU_PC(0) | SOR_SEQ_CTL_PU_PC_ALT(0) |
2222 SOR_SEQ_CTL_PD_PC(8) | SOR_SEQ_CTL_PD_PC_ALT(8);
2223 tegra_sor_writel(sor, value, SOR_SEQ_CTL);
2224
2225 value = SOR_SEQ_INST_DRIVE_PWM_OUT_LO | SOR_SEQ_INST_HALT |
2226 SOR_SEQ_INST_WAIT_VSYNC | SOR_SEQ_INST_WAIT(1);
2227 tegra_sor_writel(sor, value, SOR_SEQ_INST(0));
2228 tegra_sor_writel(sor, value, SOR_SEQ_INST(8));
2229
Thierry Redingc57997b2017-10-12 19:12:57 +02002230 if (!sor->soc->has_nvdisplay) {
2231 /* program the reference clock */
2232 value = SOR_REFCLK_DIV_INT(div) | SOR_REFCLK_DIV_FRAC(div);
2233 tegra_sor_writel(sor, value, SOR_REFCLK);
2234 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002235
Thierry Reding30b49432015-08-03 15:50:32 +02002236 /* XXX not in TRM */
2237 for (value = 0, i = 0; i < 5; i++)
2238 value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->soc->xbar_cfg[i]) |
2239 SOR_XBAR_CTRL_LINK1_XSEL(i, i);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002240
2241 tegra_sor_writel(sor, 0x00000000, SOR_XBAR_POL);
Thierry Reding30b49432015-08-03 15:50:32 +02002242 tegra_sor_writel(sor, value, SOR_XBAR_CTRL);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002243
Thierry Reding25bb2ce2015-08-03 14:23:29 +02002244 /* switch to parent clock */
Thierry Redinge1335e22017-10-12 17:53:11 +02002245 err = clk_set_parent(sor->clk, sor->clk_parent);
2246 if (err < 0) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002247 dev_err(sor->dev, "failed to set parent clock: %d\n", err);
Thierry Redinge1335e22017-10-12 17:53:11 +02002248 return;
2249 }
2250
2251 err = tegra_sor_set_parent_clock(sor, sor->clk_pad);
2252 if (err < 0) {
2253 dev_err(sor->dev, "failed to set pad clock: %d\n", err);
2254 return;
2255 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002256
Thierry Reding459cc2c2015-07-30 10:34:24 +02002257
Thierry Redingc57997b2017-10-12 19:12:57 +02002258 if (!sor->soc->has_nvdisplay) {
2259 value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002260
Thierry Redingc57997b2017-10-12 19:12:57 +02002261 /* XXX is this the proper check? */
2262 if (mode->clock < 75000)
2263 value |= SOR_INPUT_CONTROL_ARM_VIDEO_RANGE_LIMITED;
2264
2265 tegra_sor_writel(sor, value, SOR_INPUT_CONTROL);
2266 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002267
2268 max_ac = ((mode->htotal - mode->hdisplay) - SOR_REKEY - 18) / 32;
2269
2270 value = SOR_HDMI_CTRL_ENABLE | SOR_HDMI_CTRL_MAX_AC_PACKET(max_ac) |
2271 SOR_HDMI_CTRL_AUDIO_LAYOUT | SOR_HDMI_CTRL_REKEY(SOR_REKEY);
2272 tegra_sor_writel(sor, value, SOR_HDMI_CTRL);
2273
Thierry Redingc57997b2017-10-12 19:12:57 +02002274 if (!dc->soc->has_nvdisplay) {
2275 /* H_PULSE2 setup */
2276 pulse_start = h_ref_to_sync +
2277 (mode->hsync_end - mode->hsync_start) +
2278 (mode->htotal - mode->hsync_end) - 10;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002279
Thierry Redingc57997b2017-10-12 19:12:57 +02002280 value = PULSE_LAST_END_A | PULSE_QUAL_VACTIVE |
2281 PULSE_POLARITY_HIGH | PULSE_MODE_NORMAL;
2282 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002283
Thierry Redingc57997b2017-10-12 19:12:57 +02002284 value = PULSE_END(pulse_start + 8) | PULSE_START(pulse_start);
2285 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002286
Thierry Redingc57997b2017-10-12 19:12:57 +02002287 value = tegra_dc_readl(dc, DC_DISP_DISP_SIGNAL_OPTIONS0);
2288 value |= H_PULSE2_ENABLE;
2289 tegra_dc_writel(dc, value, DC_DISP_DISP_SIGNAL_OPTIONS0);
2290 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002291
2292 /* infoframe setup */
2293 err = tegra_sor_hdmi_setup_avi_infoframe(sor, mode);
2294 if (err < 0)
2295 dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
2296
2297 /* XXX HDMI audio support not implemented yet */
2298 tegra_sor_hdmi_disable_audio_infoframe(sor);
2299
2300 /* use single TMDS protocol */
2301 value = tegra_sor_readl(sor, SOR_STATE1);
2302 value &= ~SOR_STATE_ASY_PROTOCOL_MASK;
2303 value |= SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A;
2304 tegra_sor_writel(sor, value, SOR_STATE1);
2305
2306 /* power up pad calibration */
Thierry Reding880cee02017-10-12 19:04:17 +02002307 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002308 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
Thierry Reding880cee02017-10-12 19:04:17 +02002309 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002310
2311 /* production settings */
2312 settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000);
Dan Carpenterdb8b42f2015-08-17 17:37:03 +03002313 if (!settings) {
2314 dev_err(sor->dev, "no settings for pixel clock %d Hz\n",
2315 mode->clock * 1000);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002316 return;
2317 }
2318
Thierry Reding880cee02017-10-12 19:04:17 +02002319 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002320 value &= ~SOR_PLL0_ICHPMP_MASK;
Thierry Redingc57997b2017-10-12 19:12:57 +02002321 value &= ~SOR_PLL0_FILTER_MASK;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002322 value &= ~SOR_PLL0_VCOCAP_MASK;
2323 value |= SOR_PLL0_ICHPMP(settings->ichpmp);
Thierry Redingc57997b2017-10-12 19:12:57 +02002324 value |= SOR_PLL0_FILTER(settings->filter);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002325 value |= SOR_PLL0_VCOCAP(settings->vcocap);
Thierry Reding880cee02017-10-12 19:04:17 +02002326 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002327
Thierry Redingc57997b2017-10-12 19:12:57 +02002328 /* XXX not in TRM */
Thierry Reding880cee02017-10-12 19:04:17 +02002329 value = tegra_sor_readl(sor, sor->soc->regs->pll1);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002330 value &= ~SOR_PLL1_LOADADJ_MASK;
Thierry Redingc57997b2017-10-12 19:12:57 +02002331 value &= ~SOR_PLL1_TMDS_TERMADJ_MASK;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002332 value |= SOR_PLL1_LOADADJ(settings->loadadj);
Thierry Redingc57997b2017-10-12 19:12:57 +02002333 value |= SOR_PLL1_TMDS_TERMADJ(settings->tmds_termadj);
2334 value |= SOR_PLL1_TMDS_TERM;
Thierry Reding880cee02017-10-12 19:04:17 +02002335 tegra_sor_writel(sor, value, sor->soc->regs->pll1);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002336
Thierry Reding880cee02017-10-12 19:04:17 +02002337 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
Thierry Redingc57997b2017-10-12 19:12:57 +02002338 value &= ~SOR_PLL3_BG_TEMP_COEF_MASK;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002339 value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK;
Thierry Redingc57997b2017-10-12 19:12:57 +02002340 value &= ~SOR_PLL3_AVDD10_LEVEL_MASK;
2341 value &= ~SOR_PLL3_AVDD14_LEVEL_MASK;
2342 value |= SOR_PLL3_BG_TEMP_COEF(settings->bg_temp_coef);
2343 value |= SOR_PLL3_BG_VREF_LEVEL(settings->bg_vref_level);
2344 value |= SOR_PLL3_AVDD10_LEVEL(settings->avdd10_level);
2345 value |= SOR_PLL3_AVDD14_LEVEL(settings->avdd14_level);
Thierry Reding880cee02017-10-12 19:04:17 +02002346 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002347
Thierry Redingc57997b2017-10-12 19:12:57 +02002348 value = settings->drive_current[3] << 24 |
2349 settings->drive_current[2] << 16 |
2350 settings->drive_current[1] << 8 |
2351 settings->drive_current[0] << 0;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002352 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0);
2353
Thierry Redingc57997b2017-10-12 19:12:57 +02002354 value = settings->preemphasis[3] << 24 |
2355 settings->preemphasis[2] << 16 |
2356 settings->preemphasis[1] << 8 |
2357 settings->preemphasis[0] << 0;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002358 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
2359
Thierry Reding880cee02017-10-12 19:04:17 +02002360 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002361 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
2362 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
Thierry Redingc57997b2017-10-12 19:12:57 +02002363 value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu_value);
Thierry Reding880cee02017-10-12 19:04:17 +02002364 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002365
Thierry Redingc57997b2017-10-12 19:12:57 +02002366 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl2);
2367 value &= ~SOR_DP_PADCTL_SPAREPLL_MASK;
2368 value |= SOR_DP_PADCTL_SPAREPLL(settings->sparepll);
2369 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl2);
2370
Thierry Reding459cc2c2015-07-30 10:34:24 +02002371 /* power down pad calibration */
Thierry Reding880cee02017-10-12 19:04:17 +02002372 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002373 value |= SOR_DP_PADCTL_PAD_CAL_PD;
Thierry Reding880cee02017-10-12 19:04:17 +02002374 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002375
Thierry Redingc57997b2017-10-12 19:12:57 +02002376 if (!dc->soc->has_nvdisplay) {
2377 /* miscellaneous display controller settings */
2378 value = VSYNC_H_POSITION(1);
2379 tegra_dc_writel(dc, value, DC_DISP_DISP_TIMING_OPTIONS);
2380 }
Thierry Reding459cc2c2015-07-30 10:34:24 +02002381
2382 value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
2383 value &= ~DITHER_CONTROL_MASK;
2384 value &= ~BASE_COLOR_SIZE_MASK;
2385
Thierry Redingc31efa72015-09-08 16:09:22 +02002386 switch (state->bpc) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002387 case 6:
2388 value |= BASE_COLOR_SIZE_666;
2389 break;
2390
2391 case 8:
2392 value |= BASE_COLOR_SIZE_888;
2393 break;
2394
Thierry Redingc57997b2017-10-12 19:12:57 +02002395 case 10:
2396 value |= BASE_COLOR_SIZE_101010;
2397 break;
2398
2399 case 12:
2400 value |= BASE_COLOR_SIZE_121212;
2401 break;
2402
Thierry Reding459cc2c2015-07-30 10:34:24 +02002403 default:
Thierry Redingc31efa72015-09-08 16:09:22 +02002404 WARN(1, "%u bits-per-color not supported\n", state->bpc);
2405 value |= BASE_COLOR_SIZE_888;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002406 break;
2407 }
2408
2409 tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
2410
Thierry Redingc57997b2017-10-12 19:12:57 +02002411 /* XXX set display head owner */
2412 value = tegra_sor_readl(sor, SOR_STATE1);
2413 value &= ~SOR_STATE_ASY_OWNER_MASK;
2414 value |= SOR_STATE_ASY_OWNER(1 + dc->pipe);
2415 tegra_sor_writel(sor, value, SOR_STATE1);
2416
Thierry Reding459cc2c2015-07-30 10:34:24 +02002417 err = tegra_sor_power_up(sor, 250);
2418 if (err < 0)
2419 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
2420
Thierry Reding2bd1dd32015-08-03 15:46:15 +02002421 /* configure dynamic range of output */
Thierry Reding880cee02017-10-12 19:04:17 +02002422 value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002423 value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK;
2424 value &= ~SOR_HEAD_STATE_DYNRANGE_MASK;
Thierry Reding880cee02017-10-12 19:04:17 +02002425 tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002426
Thierry Reding2bd1dd32015-08-03 15:46:15 +02002427 /* configure colorspace */
Thierry Reding880cee02017-10-12 19:04:17 +02002428 value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002429 value &= ~SOR_HEAD_STATE_COLORSPACE_MASK;
2430 value |= SOR_HEAD_STATE_COLORSPACE_RGB;
Thierry Reding880cee02017-10-12 19:04:17 +02002431 tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002432
Thierry Redingc31efa72015-09-08 16:09:22 +02002433 tegra_sor_mode_set(sor, mode, state);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002434
2435 tegra_sor_update(sor);
2436
Thierry Redingc57997b2017-10-12 19:12:57 +02002437 /* program preamble timing in SOR (XXX) */
2438 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
2439 value &= ~SOR_DP_SPARE_DISP_VIDEO_PREAMBLE;
2440 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
2441
Thierry Reding459cc2c2015-07-30 10:34:24 +02002442 err = tegra_sor_attach(sor);
2443 if (err < 0)
2444 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
2445
2446 /* enable display to SOR clock and generate HDMI preamble */
2447 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc57997b2017-10-12 19:12:57 +02002448
2449 if (!sor->soc->has_nvdisplay)
2450 value |= SOR_ENABLE(1) | SOR1_TIMING_CYA;
2451 else
2452 value |= SOR_ENABLE(sor->index);
2453
Thierry Reding459cc2c2015-07-30 10:34:24 +02002454 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
2455
Thierry Redingc57997b2017-10-12 19:12:57 +02002456 if (dc->soc->has_nvdisplay) {
2457 value = tegra_dc_readl(dc, DC_DISP_CORE_SOR_SET_CONTROL(sor->index));
2458 value &= ~PROTOCOL_MASK;
2459 value |= PROTOCOL_SINGLE_TMDS_A;
2460 tegra_dc_writel(dc, value, DC_DISP_CORE_SOR_SET_CONTROL(sor->index));
2461 }
2462
Thierry Reding459cc2c2015-07-30 10:34:24 +02002463 tegra_dc_commit(dc);
2464
2465 err = tegra_sor_wakeup(sor);
2466 if (err < 0)
2467 dev_err(sor->dev, "failed to wakeup SOR: %d\n", err);
2468}
2469
2470static const struct drm_encoder_helper_funcs tegra_sor_hdmi_helpers = {
2471 .disable = tegra_sor_hdmi_disable,
2472 .enable = tegra_sor_hdmi_enable,
2473 .atomic_check = tegra_sor_encoder_atomic_check,
2474};
2475
Thierry Reding6b6b6042013-11-15 16:06:05 +01002476static int tegra_sor_init(struct host1x_client *client)
2477{
Thierry Reding9910f5c2014-05-22 09:57:15 +02002478 struct drm_device *drm = dev_get_drvdata(client->parent);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002479 const struct drm_encoder_helper_funcs *helpers = NULL;
Thierry Reding6b6b6042013-11-15 16:06:05 +01002480 struct tegra_sor *sor = host1x_client_to_sor(client);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002481 int connector = DRM_MODE_CONNECTOR_Unknown;
2482 int encoder = DRM_MODE_ENCODER_NONE;
Thierry Reding6b6b6042013-11-15 16:06:05 +01002483 int err;
2484
Thierry Reding9542c232015-07-08 13:39:09 +02002485 if (!sor->aux) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002486 if (sor->soc->supports_hdmi) {
2487 connector = DRM_MODE_CONNECTOR_HDMIA;
2488 encoder = DRM_MODE_ENCODER_TMDS;
2489 helpers = &tegra_sor_hdmi_helpers;
2490 } else if (sor->soc->supports_lvds) {
2491 connector = DRM_MODE_CONNECTOR_LVDS;
2492 encoder = DRM_MODE_ENCODER_LVDS;
2493 }
2494 } else {
2495 if (sor->soc->supports_edp) {
2496 connector = DRM_MODE_CONNECTOR_eDP;
2497 encoder = DRM_MODE_ENCODER_TMDS;
2498 helpers = &tegra_sor_edp_helpers;
2499 } else if (sor->soc->supports_dp) {
2500 connector = DRM_MODE_CONNECTOR_DisplayPort;
2501 encoder = DRM_MODE_ENCODER_TMDS;
2502 }
2503 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002504
Thierry Reding6b6b6042013-11-15 16:06:05 +01002505 sor->output.dev = sor->dev;
Thierry Reding6b6b6042013-11-15 16:06:05 +01002506
Thierry Reding6fad8f62014-11-28 15:41:34 +01002507 drm_connector_init(drm, &sor->output.connector,
2508 &tegra_sor_connector_funcs,
Thierry Reding459cc2c2015-07-30 10:34:24 +02002509 connector);
Thierry Reding6fad8f62014-11-28 15:41:34 +01002510 drm_connector_helper_add(&sor->output.connector,
2511 &tegra_sor_connector_helper_funcs);
2512 sor->output.connector.dpms = DRM_MODE_DPMS_OFF;
2513
Thierry Reding6fad8f62014-11-28 15:41:34 +01002514 drm_encoder_init(drm, &sor->output.encoder, &tegra_sor_encoder_funcs,
Ville Syrjälä13a3d912015-12-09 16:20:18 +02002515 encoder, NULL);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002516 drm_encoder_helper_add(&sor->output.encoder, helpers);
Thierry Reding6fad8f62014-11-28 15:41:34 +01002517
2518 drm_mode_connector_attach_encoder(&sor->output.connector,
2519 &sor->output.encoder);
2520 drm_connector_register(&sor->output.connector);
2521
Thierry Redingea130b22014-12-19 15:51:35 +01002522 err = tegra_output_init(drm, &sor->output);
2523 if (err < 0) {
2524 dev_err(client->dev, "failed to initialize output: %d\n", err);
2525 return err;
2526 }
Thierry Reding6fad8f62014-11-28 15:41:34 +01002527
Thierry Redingc57997b2017-10-12 19:12:57 +02002528 tegra_output_find_possible_crtcs(&sor->output, drm);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002529
Thierry Reding9542c232015-07-08 13:39:09 +02002530 if (sor->aux) {
2531 err = drm_dp_aux_attach(sor->aux, &sor->output);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002532 if (err < 0) {
2533 dev_err(sor->dev, "failed to attach DP: %d\n", err);
2534 return err;
2535 }
2536 }
2537
Tomeu Vizoso535a65d2015-03-30 10:33:03 +02002538 /*
2539 * XXX: Remove this reset once proper hand-over from firmware to
2540 * kernel is possible.
2541 */
Jon Hunterf8c79122016-07-01 14:21:38 +01002542 if (sor->rst) {
2543 err = reset_control_assert(sor->rst);
2544 if (err < 0) {
2545 dev_err(sor->dev, "failed to assert SOR reset: %d\n",
2546 err);
2547 return err;
2548 }
Tomeu Vizoso535a65d2015-03-30 10:33:03 +02002549 }
2550
Thierry Reding6fad8f62014-11-28 15:41:34 +01002551 err = clk_prepare_enable(sor->clk);
2552 if (err < 0) {
2553 dev_err(sor->dev, "failed to enable clock: %d\n", err);
2554 return err;
2555 }
2556
Tomeu Vizoso535a65d2015-03-30 10:33:03 +02002557 usleep_range(1000, 3000);
2558
Jon Hunterf8c79122016-07-01 14:21:38 +01002559 if (sor->rst) {
2560 err = reset_control_deassert(sor->rst);
2561 if (err < 0) {
2562 dev_err(sor->dev, "failed to deassert SOR reset: %d\n",
2563 err);
2564 return err;
2565 }
Tomeu Vizoso535a65d2015-03-30 10:33:03 +02002566 }
2567
Thierry Reding6fad8f62014-11-28 15:41:34 +01002568 err = clk_prepare_enable(sor->clk_safe);
2569 if (err < 0)
2570 return err;
2571
2572 err = clk_prepare_enable(sor->clk_dp);
2573 if (err < 0)
2574 return err;
2575
Thierry Reding6b6b6042013-11-15 16:06:05 +01002576 return 0;
2577}
2578
2579static int tegra_sor_exit(struct host1x_client *client)
2580{
2581 struct tegra_sor *sor = host1x_client_to_sor(client);
2582 int err;
2583
Thierry Reding328ec692014-12-19 15:55:08 +01002584 tegra_output_exit(&sor->output);
2585
Thierry Reding9542c232015-07-08 13:39:09 +02002586 if (sor->aux) {
2587 err = drm_dp_aux_detach(sor->aux);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002588 if (err < 0) {
2589 dev_err(sor->dev, "failed to detach DP: %d\n", err);
2590 return err;
2591 }
2592 }
2593
Thierry Reding6fad8f62014-11-28 15:41:34 +01002594 clk_disable_unprepare(sor->clk_safe);
2595 clk_disable_unprepare(sor->clk_dp);
2596 clk_disable_unprepare(sor->clk);
2597
Thierry Reding6b6b6042013-11-15 16:06:05 +01002598 return 0;
2599}
2600
2601static const struct host1x_client_ops sor_client_ops = {
2602 .init = tegra_sor_init,
2603 .exit = tegra_sor_exit,
2604};
2605
Thierry Reding459cc2c2015-07-30 10:34:24 +02002606static const struct tegra_sor_ops tegra_sor_edp_ops = {
2607 .name = "eDP",
2608};
2609
2610static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
2611{
2612 int err;
2613
2614 sor->avdd_io_supply = devm_regulator_get(sor->dev, "avdd-io");
2615 if (IS_ERR(sor->avdd_io_supply)) {
2616 dev_err(sor->dev, "cannot get AVDD I/O supply: %ld\n",
2617 PTR_ERR(sor->avdd_io_supply));
2618 return PTR_ERR(sor->avdd_io_supply);
2619 }
2620
2621 err = regulator_enable(sor->avdd_io_supply);
2622 if (err < 0) {
2623 dev_err(sor->dev, "failed to enable AVDD I/O supply: %d\n",
2624 err);
2625 return err;
2626 }
2627
2628 sor->vdd_pll_supply = devm_regulator_get(sor->dev, "vdd-pll");
2629 if (IS_ERR(sor->vdd_pll_supply)) {
2630 dev_err(sor->dev, "cannot get VDD PLL supply: %ld\n",
2631 PTR_ERR(sor->vdd_pll_supply));
2632 return PTR_ERR(sor->vdd_pll_supply);
2633 }
2634
2635 err = regulator_enable(sor->vdd_pll_supply);
2636 if (err < 0) {
2637 dev_err(sor->dev, "failed to enable VDD PLL supply: %d\n",
2638 err);
2639 return err;
2640 }
2641
2642 sor->hdmi_supply = devm_regulator_get(sor->dev, "hdmi");
2643 if (IS_ERR(sor->hdmi_supply)) {
2644 dev_err(sor->dev, "cannot get HDMI supply: %ld\n",
2645 PTR_ERR(sor->hdmi_supply));
2646 return PTR_ERR(sor->hdmi_supply);
2647 }
2648
2649 err = regulator_enable(sor->hdmi_supply);
2650 if (err < 0) {
2651 dev_err(sor->dev, "failed to enable HDMI supply: %d\n", err);
2652 return err;
2653 }
2654
2655 return 0;
2656}
2657
2658static int tegra_sor_hdmi_remove(struct tegra_sor *sor)
2659{
2660 regulator_disable(sor->hdmi_supply);
2661 regulator_disable(sor->vdd_pll_supply);
2662 regulator_disable(sor->avdd_io_supply);
2663
2664 return 0;
2665}
2666
2667static const struct tegra_sor_ops tegra_sor_hdmi_ops = {
2668 .name = "HDMI",
2669 .probe = tegra_sor_hdmi_probe,
2670 .remove = tegra_sor_hdmi_remove,
2671};
2672
Thierry Reding30b49432015-08-03 15:50:32 +02002673static const u8 tegra124_sor_xbar_cfg[5] = {
2674 0, 1, 2, 3, 4
2675};
2676
Thierry Reding880cee02017-10-12 19:04:17 +02002677static const struct tegra_sor_regs tegra124_sor_regs = {
2678 .head_state0 = 0x05,
2679 .head_state1 = 0x07,
2680 .head_state2 = 0x09,
2681 .head_state3 = 0x0b,
2682 .head_state4 = 0x0d,
2683 .head_state5 = 0x0f,
2684 .pll0 = 0x17,
2685 .pll1 = 0x18,
2686 .pll2 = 0x19,
2687 .pll3 = 0x1a,
2688 .dp_padctl0 = 0x5c,
2689 .dp_padctl2 = 0x73,
2690};
2691
Thierry Reding459cc2c2015-07-30 10:34:24 +02002692static const struct tegra_sor_soc tegra124_sor = {
2693 .supports_edp = true,
2694 .supports_lvds = true,
2695 .supports_hdmi = false,
2696 .supports_dp = false,
Thierry Reding880cee02017-10-12 19:04:17 +02002697 .regs = &tegra124_sor_regs,
Thierry Redingc57997b2017-10-12 19:12:57 +02002698 .has_nvdisplay = false,
Thierry Reding30b49432015-08-03 15:50:32 +02002699 .xbar_cfg = tegra124_sor_xbar_cfg,
Thierry Reding459cc2c2015-07-30 10:34:24 +02002700};
2701
Thierry Reding880cee02017-10-12 19:04:17 +02002702static const struct tegra_sor_regs tegra210_sor_regs = {
2703 .head_state0 = 0x05,
2704 .head_state1 = 0x07,
2705 .head_state2 = 0x09,
2706 .head_state3 = 0x0b,
2707 .head_state4 = 0x0d,
2708 .head_state5 = 0x0f,
2709 .pll0 = 0x17,
2710 .pll1 = 0x18,
2711 .pll2 = 0x19,
2712 .pll3 = 0x1a,
2713 .dp_padctl0 = 0x5c,
2714 .dp_padctl2 = 0x73,
2715};
2716
Thierry Reding459cc2c2015-07-30 10:34:24 +02002717static const struct tegra_sor_soc tegra210_sor = {
2718 .supports_edp = true,
2719 .supports_lvds = false,
2720 .supports_hdmi = false,
2721 .supports_dp = false,
Thierry Reding880cee02017-10-12 19:04:17 +02002722 .regs = &tegra210_sor_regs,
Thierry Redingc57997b2017-10-12 19:12:57 +02002723 .has_nvdisplay = false,
Thierry Reding30b49432015-08-03 15:50:32 +02002724 .xbar_cfg = tegra124_sor_xbar_cfg,
2725};
2726
2727static const u8 tegra210_sor_xbar_cfg[5] = {
2728 2, 1, 0, 3, 4
Thierry Reding459cc2c2015-07-30 10:34:24 +02002729};
2730
2731static const struct tegra_sor_soc tegra210_sor1 = {
2732 .supports_edp = false,
2733 .supports_lvds = false,
2734 .supports_hdmi = true,
2735 .supports_dp = true,
2736
Thierry Reding880cee02017-10-12 19:04:17 +02002737 .regs = &tegra210_sor_regs,
Thierry Redingc57997b2017-10-12 19:12:57 +02002738 .has_nvdisplay = false,
Thierry Reding880cee02017-10-12 19:04:17 +02002739
Thierry Reding459cc2c2015-07-30 10:34:24 +02002740 .num_settings = ARRAY_SIZE(tegra210_sor_hdmi_defaults),
2741 .settings = tegra210_sor_hdmi_defaults,
Thierry Reding30b49432015-08-03 15:50:32 +02002742
2743 .xbar_cfg = tegra210_sor_xbar_cfg,
Thierry Reding459cc2c2015-07-30 10:34:24 +02002744};
2745
Thierry Redingc57997b2017-10-12 19:12:57 +02002746static const struct tegra_sor_regs tegra186_sor_regs = {
2747 .head_state0 = 0x151,
2748 .head_state1 = 0x154,
2749 .head_state2 = 0x157,
2750 .head_state3 = 0x15a,
2751 .head_state4 = 0x15d,
2752 .head_state5 = 0x160,
2753 .pll0 = 0x163,
2754 .pll1 = 0x164,
2755 .pll2 = 0x165,
2756 .pll3 = 0x166,
2757 .dp_padctl0 = 0x168,
2758 .dp_padctl2 = 0x16a,
2759};
2760
2761static const struct tegra_sor_soc tegra186_sor = {
2762 .supports_edp = false,
2763 .supports_lvds = false,
2764 .supports_hdmi = false,
2765 .supports_dp = true,
2766
2767 .regs = &tegra186_sor_regs,
2768 .has_nvdisplay = true,
2769
2770 .xbar_cfg = tegra124_sor_xbar_cfg,
2771};
2772
2773static const struct tegra_sor_soc tegra186_sor1 = {
2774 .supports_edp = false,
2775 .supports_lvds = false,
2776 .supports_hdmi = true,
2777 .supports_dp = true,
2778
2779 .regs = &tegra186_sor_regs,
2780 .has_nvdisplay = true,
2781
2782 .num_settings = ARRAY_SIZE(tegra186_sor_hdmi_defaults),
2783 .settings = tegra186_sor_hdmi_defaults,
2784
2785 .xbar_cfg = tegra124_sor_xbar_cfg,
2786};
2787
Thierry Reding459cc2c2015-07-30 10:34:24 +02002788static const struct of_device_id tegra_sor_of_match[] = {
Thierry Redingc57997b2017-10-12 19:12:57 +02002789 { .compatible = "nvidia,tegra186-sor1", .data = &tegra186_sor1 },
2790 { .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor },
Thierry Reding459cc2c2015-07-30 10:34:24 +02002791 { .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 },
2792 { .compatible = "nvidia,tegra210-sor", .data = &tegra210_sor },
2793 { .compatible = "nvidia,tegra124-sor", .data = &tegra124_sor },
2794 { },
2795};
2796MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
2797
Thierry Redingc57997b2017-10-12 19:12:57 +02002798static int tegra_sor_parse_dt(struct tegra_sor *sor)
2799{
2800 struct device_node *np = sor->dev->of_node;
2801 u32 value;
2802 int err;
2803
2804 if (sor->soc->has_nvdisplay) {
2805 err = of_property_read_u32(np, "nvidia,interface", &value);
2806 if (err < 0)
2807 return err;
2808
2809 sor->index = value;
2810
2811 /*
2812 * override the default that we already set for Tegra210 and
2813 * earlier
2814 */
2815 sor->pad = TEGRA_IO_PAD_HDMI_DP0 + sor->index;
2816 }
2817
2818 return 0;
2819}
2820
Thierry Reding6b6b6042013-11-15 16:06:05 +01002821static int tegra_sor_probe(struct platform_device *pdev)
2822{
2823 struct device_node *np;
2824 struct tegra_sor *sor;
2825 struct resource *regs;
2826 int err;
2827
2828 sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL);
2829 if (!sor)
2830 return -ENOMEM;
2831
Thierry Reding5faea3d2017-08-21 17:33:14 +02002832 sor->soc = of_device_get_match_data(&pdev->dev);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002833 sor->output.dev = sor->dev = &pdev->dev;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002834
2835 sor->settings = devm_kmemdup(&pdev->dev, sor->soc->settings,
2836 sor->soc->num_settings *
2837 sizeof(*sor->settings),
2838 GFP_KERNEL);
2839 if (!sor->settings)
2840 return -ENOMEM;
2841
2842 sor->num_settings = sor->soc->num_settings;
Thierry Reding6b6b6042013-11-15 16:06:05 +01002843
2844 np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
2845 if (np) {
Thierry Reding9542c232015-07-08 13:39:09 +02002846 sor->aux = drm_dp_aux_find_by_of_node(np);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002847 of_node_put(np);
2848
Thierry Reding9542c232015-07-08 13:39:09 +02002849 if (!sor->aux)
Thierry Reding6b6b6042013-11-15 16:06:05 +01002850 return -EPROBE_DEFER;
2851 }
2852
Thierry Reding9542c232015-07-08 13:39:09 +02002853 if (!sor->aux) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002854 if (sor->soc->supports_hdmi) {
2855 sor->ops = &tegra_sor_hdmi_ops;
Thierry Redingc57997b2017-10-12 19:12:57 +02002856 sor->pad = TEGRA_IO_PAD_HDMI;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002857 } else if (sor->soc->supports_lvds) {
2858 dev_err(&pdev->dev, "LVDS not supported yet\n");
2859 return -ENODEV;
2860 } else {
2861 dev_err(&pdev->dev, "unknown (non-DP) support\n");
2862 return -ENODEV;
2863 }
2864 } else {
2865 if (sor->soc->supports_edp) {
2866 sor->ops = &tegra_sor_edp_ops;
Thierry Redingc57997b2017-10-12 19:12:57 +02002867 sor->pad = TEGRA_IO_PAD_LVDS;
Thierry Reding459cc2c2015-07-30 10:34:24 +02002868 } else if (sor->soc->supports_dp) {
2869 dev_err(&pdev->dev, "DisplayPort not supported yet\n");
2870 return -ENODEV;
2871 } else {
2872 dev_err(&pdev->dev, "unknown (DP) support\n");
2873 return -ENODEV;
2874 }
2875 }
2876
Thierry Redingc57997b2017-10-12 19:12:57 +02002877 err = tegra_sor_parse_dt(sor);
2878 if (err < 0)
2879 return err;
2880
Thierry Reding6b6b6042013-11-15 16:06:05 +01002881 err = tegra_output_probe(&sor->output);
Thierry Reding4dbdc742015-04-27 15:04:26 +02002882 if (err < 0) {
2883 dev_err(&pdev->dev, "failed to probe output: %d\n", err);
Thierry Reding6b6b6042013-11-15 16:06:05 +01002884 return err;
Thierry Reding4dbdc742015-04-27 15:04:26 +02002885 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002886
Thierry Reding459cc2c2015-07-30 10:34:24 +02002887 if (sor->ops && sor->ops->probe) {
2888 err = sor->ops->probe(sor);
2889 if (err < 0) {
2890 dev_err(&pdev->dev, "failed to probe %s: %d\n",
2891 sor->ops->name, err);
2892 goto output;
2893 }
2894 }
2895
Thierry Reding6b6b6042013-11-15 16:06:05 +01002896 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2897 sor->regs = devm_ioremap_resource(&pdev->dev, regs);
Thierry Reding459cc2c2015-07-30 10:34:24 +02002898 if (IS_ERR(sor->regs)) {
2899 err = PTR_ERR(sor->regs);
2900 goto remove;
2901 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002902
Jon Hunterf8c79122016-07-01 14:21:38 +01002903 if (!pdev->dev.pm_domain) {
2904 sor->rst = devm_reset_control_get(&pdev->dev, "sor");
2905 if (IS_ERR(sor->rst)) {
2906 err = PTR_ERR(sor->rst);
2907 dev_err(&pdev->dev, "failed to get reset control: %d\n",
2908 err);
2909 goto remove;
2910 }
Thierry Reding4dbdc742015-04-27 15:04:26 +02002911 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002912
2913 sor->clk = devm_clk_get(&pdev->dev, NULL);
Thierry Reding4dbdc742015-04-27 15:04:26 +02002914 if (IS_ERR(sor->clk)) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002915 err = PTR_ERR(sor->clk);
2916 dev_err(&pdev->dev, "failed to get module clock: %d\n", err);
2917 goto remove;
Thierry Reding4dbdc742015-04-27 15:04:26 +02002918 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002919
Thierry Reding618dee32016-06-09 17:53:57 +02002920 if (sor->soc->supports_hdmi || sor->soc->supports_dp) {
Thierry Redinge1335e22017-10-12 17:53:11 +02002921 struct device_node *np = pdev->dev.of_node;
2922 const char *name;
2923
2924 /*
2925 * For backwards compatibility with Tegra210 device trees,
2926 * fall back to the old clock name "source" if the new "out"
2927 * clock is not available.
2928 */
2929 if (of_property_match_string(np, "clock-names", "out") < 0)
2930 name = "source";
2931 else
2932 name = "out";
2933
2934 sor->clk_out = devm_clk_get(&pdev->dev, name);
2935 if (IS_ERR(sor->clk_out)) {
2936 err = PTR_ERR(sor->clk_out);
2937 dev_err(sor->dev, "failed to get %s clock: %d\n",
2938 name, err);
Thierry Reding618dee32016-06-09 17:53:57 +02002939 goto remove;
2940 }
2941 }
2942
Thierry Reding6b6b6042013-11-15 16:06:05 +01002943 sor->clk_parent = devm_clk_get(&pdev->dev, "parent");
Thierry Reding4dbdc742015-04-27 15:04:26 +02002944 if (IS_ERR(sor->clk_parent)) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002945 err = PTR_ERR(sor->clk_parent);
2946 dev_err(&pdev->dev, "failed to get parent clock: %d\n", err);
2947 goto remove;
Thierry Reding4dbdc742015-04-27 15:04:26 +02002948 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002949
Thierry Reding6b6b6042013-11-15 16:06:05 +01002950 sor->clk_safe = devm_clk_get(&pdev->dev, "safe");
Thierry Reding4dbdc742015-04-27 15:04:26 +02002951 if (IS_ERR(sor->clk_safe)) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002952 err = PTR_ERR(sor->clk_safe);
2953 dev_err(&pdev->dev, "failed to get safe clock: %d\n", err);
2954 goto remove;
Thierry Reding4dbdc742015-04-27 15:04:26 +02002955 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002956
Thierry Reding6b6b6042013-11-15 16:06:05 +01002957 sor->clk_dp = devm_clk_get(&pdev->dev, "dp");
Thierry Reding4dbdc742015-04-27 15:04:26 +02002958 if (IS_ERR(sor->clk_dp)) {
Thierry Reding459cc2c2015-07-30 10:34:24 +02002959 err = PTR_ERR(sor->clk_dp);
2960 dev_err(&pdev->dev, "failed to get DP clock: %d\n", err);
2961 goto remove;
Thierry Reding4dbdc742015-04-27 15:04:26 +02002962 }
Thierry Reding6b6b6042013-11-15 16:06:05 +01002963
Thierry Redinge1335e22017-10-12 17:53:11 +02002964 /*
2965 * Starting with Tegra186, the BPMP provides an implementation for
2966 * the pad output clock, so we have to look it up from device tree.
2967 */
2968 sor->clk_pad = devm_clk_get(&pdev->dev, "pad");
2969 if (IS_ERR(sor->clk_pad)) {
2970 if (sor->clk_pad != ERR_PTR(-ENOENT)) {
2971 err = PTR_ERR(sor->clk_pad);
2972 goto remove;
2973 }
2974
2975 /*
2976 * If the pad output clock is not available, then we assume
2977 * we're on Tegra210 or earlier and have to provide our own
2978 * implementation.
2979 */
2980 sor->clk_pad = NULL;
2981 }
2982
2983 /*
2984 * The bootloader may have set up the SOR such that it's module clock
2985 * is sourced by one of the display PLLs. However, that doesn't work
2986 * without properly having set up other bits of the SOR.
2987 */
2988 err = clk_set_parent(sor->clk_out, sor->clk_safe);
2989 if (err < 0) {
2990 dev_err(&pdev->dev, "failed to use safe clock: %d\n", err);
2991 goto remove;
2992 }
2993
Thierry Redingaaff8bd2015-08-07 16:04:54 +02002994 platform_set_drvdata(pdev, sor);
2995 pm_runtime_enable(&pdev->dev);
2996
Thierry Redinge1335e22017-10-12 17:53:11 +02002997 /*
2998 * On Tegra210 and earlier, provide our own implementation for the
2999 * pad output clock.
3000 */
3001 if (!sor->clk_pad) {
3002 err = pm_runtime_get_sync(&pdev->dev);
3003 if (err < 0) {
3004 dev_err(&pdev->dev, "failed to get runtime PM: %d\n",
3005 err);
3006 goto remove;
3007 }
Thierry Redingb2992212015-10-01 14:25:03 +02003008
Thierry Redinge1335e22017-10-12 17:53:11 +02003009 sor->clk_pad = tegra_clk_sor_pad_register(sor,
3010 "sor1_pad_clkout");
3011 pm_runtime_put(&pdev->dev);
3012 }
3013
3014 if (IS_ERR(sor->clk_pad)) {
3015 err = PTR_ERR(sor->clk_pad);
3016 dev_err(&pdev->dev, "failed to register SOR pad clock: %d\n",
3017 err);
Thierry Redingb2992212015-10-01 14:25:03 +02003018 goto remove;
3019 }
3020
Thierry Reding6b6b6042013-11-15 16:06:05 +01003021 INIT_LIST_HEAD(&sor->client.list);
3022 sor->client.ops = &sor_client_ops;
3023 sor->client.dev = &pdev->dev;
3024
Thierry Reding6b6b6042013-11-15 16:06:05 +01003025 err = host1x_client_register(&sor->client);
3026 if (err < 0) {
3027 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
3028 err);
Thierry Reding459cc2c2015-07-30 10:34:24 +02003029 goto remove;
Thierry Reding6b6b6042013-11-15 16:06:05 +01003030 }
3031
Thierry Reding6b6b6042013-11-15 16:06:05 +01003032 return 0;
Thierry Reding459cc2c2015-07-30 10:34:24 +02003033
3034remove:
3035 if (sor->ops && sor->ops->remove)
3036 sor->ops->remove(sor);
3037output:
3038 tegra_output_remove(&sor->output);
3039 return err;
Thierry Reding6b6b6042013-11-15 16:06:05 +01003040}
3041
3042static int tegra_sor_remove(struct platform_device *pdev)
3043{
3044 struct tegra_sor *sor = platform_get_drvdata(pdev);
3045 int err;
3046
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003047 pm_runtime_disable(&pdev->dev);
3048
Thierry Reding6b6b6042013-11-15 16:06:05 +01003049 err = host1x_client_unregister(&sor->client);
3050 if (err < 0) {
3051 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
3052 err);
3053 return err;
3054 }
3055
Thierry Reding459cc2c2015-07-30 10:34:24 +02003056 if (sor->ops && sor->ops->remove) {
3057 err = sor->ops->remove(sor);
3058 if (err < 0)
3059 dev_err(&pdev->dev, "failed to remove SOR: %d\n", err);
3060 }
3061
Thierry Reding328ec692014-12-19 15:55:08 +01003062 tegra_output_remove(&sor->output);
Thierry Reding6b6b6042013-11-15 16:06:05 +01003063
3064 return 0;
3065}
3066
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003067#ifdef CONFIG_PM
3068static int tegra_sor_suspend(struct device *dev)
3069{
3070 struct tegra_sor *sor = dev_get_drvdata(dev);
3071 int err;
3072
Jon Hunterf8c79122016-07-01 14:21:38 +01003073 if (sor->rst) {
3074 err = reset_control_assert(sor->rst);
3075 if (err < 0) {
3076 dev_err(dev, "failed to assert reset: %d\n", err);
3077 return err;
3078 }
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003079 }
3080
3081 usleep_range(1000, 2000);
3082
3083 clk_disable_unprepare(sor->clk);
3084
3085 return 0;
3086}
3087
3088static int tegra_sor_resume(struct device *dev)
3089{
3090 struct tegra_sor *sor = dev_get_drvdata(dev);
3091 int err;
3092
3093 err = clk_prepare_enable(sor->clk);
3094 if (err < 0) {
3095 dev_err(dev, "failed to enable clock: %d\n", err);
3096 return err;
3097 }
3098
3099 usleep_range(1000, 2000);
3100
Jon Hunterf8c79122016-07-01 14:21:38 +01003101 if (sor->rst) {
3102 err = reset_control_deassert(sor->rst);
3103 if (err < 0) {
3104 dev_err(dev, "failed to deassert reset: %d\n", err);
3105 clk_disable_unprepare(sor->clk);
3106 return err;
3107 }
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003108 }
3109
3110 return 0;
3111}
3112#endif
3113
3114static const struct dev_pm_ops tegra_sor_pm_ops = {
3115 SET_RUNTIME_PM_OPS(tegra_sor_suspend, tegra_sor_resume, NULL)
3116};
3117
Thierry Reding6b6b6042013-11-15 16:06:05 +01003118struct platform_driver tegra_sor_driver = {
3119 .driver = {
3120 .name = "tegra-sor",
3121 .of_match_table = tegra_sor_of_match,
Thierry Redingaaff8bd2015-08-07 16:04:54 +02003122 .pm = &tegra_sor_pm_ops,
Thierry Reding6b6b6042013-11-15 16:06:05 +01003123 },
3124 .probe = tegra_sor_probe,
3125 .remove = tegra_sor_remove,
3126};