aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2017-10-12 13:12:57 -0400
committerThierry Reding <treding@nvidia.com>2017-12-13 08:36:36 -0500
commitc57997bce423fb71334a1fefa524569e48a1718f (patch)
treecc01f3938060f960a0b8b3f3a52f17408ad47389
parent880cee0b7ff379ebcf1f3d839fa59d1bcd726797 (diff)
drm/tegra: sor: Add Tegra186 support
The SOR found on Tegra186 is very similar to the one found on Tegra210 and earlier. However, due to some changes in the display architecture, some programming sequences have changed and some register have moved around. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/gpu/drm/tegra/dc.c13
-rw-r--r--drivers/gpu/drm/tegra/dc.h5
-rw-r--r--drivers/gpu/drm/tegra/drm.c2
-rw-r--r--drivers/gpu/drm/tegra/drm.h2
-rw-r--r--drivers/gpu/drm/tegra/output.c24
-rw-r--r--drivers/gpu/drm/tegra/sor.c487
-rw-r--r--drivers/gpu/drm/tegra/sor.h12
7 files changed, 422 insertions, 123 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 6790e2d869c4..906752d86622 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -54,6 +54,19 @@ static u32 tegra_dc_readl_active(struct tegra_dc *dc, unsigned long offset)
54 return value; 54 return value;
55} 55}
56 56
57bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev)
58{
59 struct device_node *np = dc->dev->of_node;
60 struct of_phandle_iterator it;
61 int err;
62
63 of_for_each_phandle(&it, err, np, "nvidia,outputs", NULL, 0)
64 if (it.node == dev->of_node)
65 return true;
66
67 return false;
68}
69
57/* 70/*
58 * Double-buffered registers have two copies: ASSEMBLY and ACTIVE. When the 71 * Double-buffered registers have two copies: ASSEMBLY and ACTIVE. When the
59 * *_ACT_REQ bits are set the ASSEMBLY copy is latched into the ACTIVE copy. 72 * *_ACT_REQ bits are set the ASSEMBLY copy is latched into the ACTIVE copy.
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 018fea74fb50..336d2c22f521 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -141,6 +141,7 @@ struct tegra_dc_window {
141}; 141};
142 142
143/* from dc.c */ 143/* from dc.c */
144bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev);
144void tegra_dc_commit(struct tegra_dc *dc); 145void tegra_dc_commit(struct tegra_dc *dc);
145int tegra_dc_state_setup_clock(struct tegra_dc *dc, 146int tegra_dc_state_setup_clock(struct tegra_dc *dc,
146 struct drm_crtc_state *crtc_state, 147 struct drm_crtc_state *crtc_state,
@@ -289,10 +290,10 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
289#define HDMI_ENABLE (1 << 30) 290#define HDMI_ENABLE (1 << 30)
290#define DSI_ENABLE (1 << 29) 291#define DSI_ENABLE (1 << 29)
291#define SOR1_TIMING_CYA (1 << 27) 292#define SOR1_TIMING_CYA (1 << 27)
292#define SOR1_ENABLE (1 << 26)
293#define SOR_ENABLE (1 << 25)
294#define CURSOR_ENABLE (1 << 16) 293#define CURSOR_ENABLE (1 << 16)
295 294
295#define SOR_ENABLE(x) (1 << (25 + (x)))
296
296#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 297#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
297#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24) 298#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
298#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16) 299#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 8ade997c2b6c..2fa1b48e14d2 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1296,6 +1296,8 @@ static const struct of_device_id host1x_drm_subdevs[] = {
1296 { .compatible = "nvidia,tegra210-vic", }, 1296 { .compatible = "nvidia,tegra210-vic", },
1297 { .compatible = "nvidia,tegra186-display", }, 1297 { .compatible = "nvidia,tegra186-display", },
1298 { .compatible = "nvidia,tegra186-dc", }, 1298 { .compatible = "nvidia,tegra186-dc", },
1299 { .compatible = "nvidia,tegra186-sor", },
1300 { .compatible = "nvidia,tegra186-sor1", },
1299 { .compatible = "nvidia,tegra186-vic", }, 1301 { .compatible = "nvidia,tegra186-vic", },
1300 { /* sentinel */ } 1302 { /* sentinel */ }
1301}; 1303};
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index d4dfd239e2a5..c52bc5978d1c 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -164,6 +164,8 @@ int tegra_output_probe(struct tegra_output *output);
164void tegra_output_remove(struct tegra_output *output); 164void tegra_output_remove(struct tegra_output *output);
165int tegra_output_init(struct drm_device *drm, struct tegra_output *output); 165int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
166void tegra_output_exit(struct tegra_output *output); 166void tegra_output_exit(struct tegra_output *output);
167void tegra_output_find_possible_crtcs(struct tegra_output *output,
168 struct drm_device *drm);
167 169
168int tegra_output_connector_get_modes(struct drm_connector *connector); 170int tegra_output_connector_get_modes(struct drm_connector *connector);
169enum drm_connector_status 171enum drm_connector_status
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index 24f8a3b712b4..ffe34bd0bb9d 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -9,7 +9,9 @@
9 9
10#include <drm/drm_atomic_helper.h> 10#include <drm/drm_atomic_helper.h>
11#include <drm/drm_panel.h> 11#include <drm/drm_panel.h>
12
12#include "drm.h" 13#include "drm.h"
14#include "dc.h"
13 15
14#include <media/cec-notifier.h> 16#include <media/cec-notifier.h>
15 17
@@ -218,3 +220,25 @@ void tegra_output_exit(struct tegra_output *output)
218 if (output->panel) 220 if (output->panel)
219 drm_panel_detach(output->panel); 221 drm_panel_detach(output->panel);
220} 222}
223
224void tegra_output_find_possible_crtcs(struct tegra_output *output,
225 struct drm_device *drm)
226{
227 struct device *dev = output->dev;
228 struct drm_crtc *crtc;
229 unsigned int mask = 0;
230
231 drm_for_each_crtc(crtc, drm) {
232 struct tegra_dc *dc = to_tegra_dc(crtc);
233
234 if (tegra_dc_has_output(dc, dev))
235 mask |= drm_crtc_mask(crtc);
236 }
237
238 if (mask == 0) {
239 dev_warn(dev, "missing output definition for heads in DT\n");
240 mask = 0x3;
241 }
242
243 output->encoder.possible_crtcs = mask;
244}
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index d51399587aca..1d7f24df0b10 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -28,17 +28,30 @@
28#include "sor.h" 28#include "sor.h"
29#include "trace.h" 29#include "trace.h"
30 30
31/*
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
31#define SOR_REKEY 0x38 39#define SOR_REKEY 0x38
32 40
33struct tegra_sor_hdmi_settings { 41struct tegra_sor_hdmi_settings {
34 unsigned long frequency; 42 unsigned long frequency;
35 43
36 u8 vcocap; 44 u8 vcocap;
45 u8 filter;
37 u8 ichpmp; 46 u8 ichpmp;
38 u8 loadadj; 47 u8 loadadj;
39 u8 termadj; 48 u8 tmds_termadj;
40 u8 tx_pu; 49 u8 tx_pu_value;
41 u8 bg_vref; 50 u8 bg_temp_coef;
51 u8 bg_vref_level;
52 u8 avdd10_level;
53 u8 avdd14_level;
54 u8 sparepll;
42 55
43 u8 drive_current[4]; 56 u8 drive_current[4];
44 u8 preemphasis[4]; 57 u8 preemphasis[4];
@@ -49,51 +62,76 @@ static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
49 { 62 {
50 .frequency = 54000000, 63 .frequency = 54000000,
51 .vcocap = 0x0, 64 .vcocap = 0x0,
65 .filter = 0x0,
52 .ichpmp = 0x1, 66 .ichpmp = 0x1,
53 .loadadj = 0x3, 67 .loadadj = 0x3,
54 .termadj = 0x9, 68 .tmds_termadj = 0x9,
55 .tx_pu = 0x10, 69 .tx_pu_value = 0x10,
56 .bg_vref = 0x8, 70 .bg_temp_coef = 0x3,
71 .bg_vref_level = 0x8,
72 .avdd10_level = 0x4,
73 .avdd14_level = 0x4,
74 .sparepll = 0x0,
57 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a }, 75 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
58 .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, 76 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
59 }, { 77 }, {
60 .frequency = 75000000, 78 .frequency = 75000000,
61 .vcocap = 0x3, 79 .vcocap = 0x3,
80 .filter = 0x0,
62 .ichpmp = 0x1, 81 .ichpmp = 0x1,
63 .loadadj = 0x3, 82 .loadadj = 0x3,
64 .termadj = 0x9, 83 .tmds_termadj = 0x9,
65 .tx_pu = 0x40, 84 .tx_pu_value = 0x40,
66 .bg_vref = 0x8, 85 .bg_temp_coef = 0x3,
86 .bg_vref_level = 0x8,
87 .avdd10_level = 0x4,
88 .avdd14_level = 0x4,
89 .sparepll = 0x0,
67 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a }, 90 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
68 .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, 91 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
69 }, { 92 }, {
70 .frequency = 150000000, 93 .frequency = 150000000,
71 .vcocap = 0x3, 94 .vcocap = 0x3,
95 .filter = 0x0,
72 .ichpmp = 0x1, 96 .ichpmp = 0x1,
73 .loadadj = 0x3, 97 .loadadj = 0x3,
74 .termadj = 0x9, 98 .tmds_termadj = 0x9,
75 .tx_pu = 0x66, 99 .tx_pu_value = 0x66,
76 .bg_vref = 0x8, 100 .bg_temp_coef = 0x3,
101 .bg_vref_level = 0x8,
102 .avdd10_level = 0x4,
103 .avdd14_level = 0x4,
104 .sparepll = 0x0,
77 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a }, 105 .drive_current = { 0x33, 0x3a, 0x3a, 0x3a },
78 .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, 106 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
79 }, { 107 }, {
80 .frequency = 300000000, 108 .frequency = 300000000,
81 .vcocap = 0x3, 109 .vcocap = 0x3,
110 .filter = 0x0,
82 .ichpmp = 0x1, 111 .ichpmp = 0x1,
83 .loadadj = 0x3, 112 .loadadj = 0x3,
84 .termadj = 0x9, 113 .tmds_termadj = 0x9,
85 .tx_pu = 0x66, 114 .tx_pu_value = 0x66,
86 .bg_vref = 0xa, 115 .bg_temp_coef = 0x3,
116 .bg_vref_level = 0xa,
117 .avdd10_level = 0x4,
118 .avdd14_level = 0x4,
119 .sparepll = 0x0,
87 .drive_current = { 0x33, 0x3f, 0x3f, 0x3f }, 120 .drive_current = { 0x33, 0x3f, 0x3f, 0x3f },
88 .preemphasis = { 0x00, 0x17, 0x17, 0x17 }, 121 .preemphasis = { 0x00, 0x17, 0x17, 0x17 },
89 }, { 122 }, {
90 .frequency = 600000000, 123 .frequency = 600000000,
91 .vcocap = 0x3, 124 .vcocap = 0x3,
125 .filter = 0x0,
92 .ichpmp = 0x1, 126 .ichpmp = 0x1,
93 .loadadj = 0x3, 127 .loadadj = 0x3,
94 .termadj = 0x9, 128 .tmds_termadj = 0x9,
95 .tx_pu = 0x66, 129 .tx_pu_value = 0x66,
96 .bg_vref = 0x8, 130 .bg_temp_coef = 0x3,
131 .bg_vref_level = 0x8,
132 .avdd10_level = 0x4,
133 .avdd14_level = 0x4,
134 .sparepll = 0x0,
97 .drive_current = { 0x33, 0x3f, 0x3f, 0x3f }, 135 .drive_current = { 0x33, 0x3f, 0x3f, 0x3f },
98 .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, 136 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
99 }, 137 },
@@ -103,47 +141,146 @@ static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
103 { 141 {
104 .frequency = 75000000, 142 .frequency = 75000000,
105 .vcocap = 0x3, 143 .vcocap = 0x3,
144 .filter = 0x0,
106 .ichpmp = 0x1, 145 .ichpmp = 0x1,
107 .loadadj = 0x3, 146 .loadadj = 0x3,
108 .termadj = 0x9, 147 .tmds_termadj = 0x9,
109 .tx_pu = 0x40, 148 .tx_pu_value = 0x40,
110 .bg_vref = 0x8, 149 .bg_temp_coef = 0x3,
150 .bg_vref_level = 0x8,
151 .avdd10_level = 0x4,
152 .avdd14_level = 0x4,
153 .sparepll = 0x0,
111 .drive_current = { 0x29, 0x29, 0x29, 0x29 }, 154 .drive_current = { 0x29, 0x29, 0x29, 0x29 },
112 .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, 155 .preemphasis = { 0x00, 0x00, 0x00, 0x00 },
113 }, { 156 }, {
114 .frequency = 150000000, 157 .frequency = 150000000,
115 .vcocap = 0x3, 158 .vcocap = 0x3,
159 .filter = 0x0,
116 .ichpmp = 0x1, 160 .ichpmp = 0x1,
117 .loadadj = 0x3, 161 .loadadj = 0x3,
118 .termadj = 0x9, 162 .tmds_termadj = 0x9,
119 .tx_pu = 0x66, 163 .tx_pu_value = 0x66,
120 .bg_vref = 0x8, 164 .bg_temp_coef = 0x3,
165 .bg_vref_level = 0x8,
166 .avdd10_level = 0x4,
167 .avdd14_level = 0x4,
168 .sparepll = 0x0,
121 .drive_current = { 0x30, 0x37, 0x37, 0x37 }, 169 .drive_current = { 0x30, 0x37, 0x37, 0x37 },
122 .preemphasis = { 0x01, 0x02, 0x02, 0x02 }, 170 .preemphasis = { 0x01, 0x02, 0x02, 0x02 },
123 }, { 171 }, {
124 .frequency = 300000000, 172 .frequency = 300000000,
125 .vcocap = 0x3, 173 .vcocap = 0x3,
174 .filter = 0x0,
126 .ichpmp = 0x6, 175 .ichpmp = 0x6,
127 .loadadj = 0x3, 176 .loadadj = 0x3,
128 .termadj = 0x9, 177 .tmds_termadj = 0x9,
129 .tx_pu = 0x66, 178 .tx_pu_value = 0x66,
130 .bg_vref = 0xf, 179 .bg_temp_coef = 0x3,
180 .bg_vref_level = 0xf,
181 .avdd10_level = 0x4,
182 .avdd14_level = 0x4,
183 .sparepll = 0x0,
131 .drive_current = { 0x30, 0x37, 0x37, 0x37 }, 184 .drive_current = { 0x30, 0x37, 0x37, 0x37 },
132 .preemphasis = { 0x10, 0x3e, 0x3e, 0x3e }, 185 .preemphasis = { 0x10, 0x3e, 0x3e, 0x3e },
133 }, { 186 }, {
134 .frequency = 600000000, 187 .frequency = 600000000,
135 .vcocap = 0x3, 188 .vcocap = 0x3,
189 .filter = 0x0,
136 .ichpmp = 0xa, 190 .ichpmp = 0xa,
137 .loadadj = 0x3, 191 .loadadj = 0x3,
138 .termadj = 0xb, 192 .tmds_termadj = 0xb,
139 .tx_pu = 0x66, 193 .tx_pu_value = 0x66,
140 .bg_vref = 0xe, 194 .bg_temp_coef = 0x3,
195 .bg_vref_level = 0xe,
196 .avdd10_level = 0x4,
197 .avdd14_level = 0x4,
198 .sparepll = 0x0,
141 .drive_current = { 0x35, 0x3e, 0x3e, 0x3e }, 199 .drive_current = { 0x35, 0x3e, 0x3e, 0x3e },
142 .preemphasis = { 0x02, 0x3f, 0x3f, 0x3f }, 200 .preemphasis = { 0x02, 0x3f, 0x3f, 0x3f },
143 }, 201 },
144}; 202};
145#endif 203#endif
146 204
205static 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
147struct tegra_sor_regs { 284struct tegra_sor_regs {
148 unsigned int head_state0; 285 unsigned int head_state0;
149 unsigned int head_state1; 286 unsigned int head_state1;
@@ -166,6 +303,7 @@ struct tegra_sor_soc {
166 bool supports_dp; 303 bool supports_dp;
167 304
168 const struct tegra_sor_regs *regs; 305 const struct tegra_sor_regs *regs;
306 bool has_nvdisplay;
169 307
170 const struct tegra_sor_hdmi_settings *settings; 308 const struct tegra_sor_hdmi_settings *settings;
171 unsigned int num_settings; 309 unsigned int num_settings;
@@ -188,6 +326,7 @@ struct tegra_sor {
188 326
189 const struct tegra_sor_soc *soc; 327 const struct tegra_sor_soc *soc;
190 void __iomem *regs; 328 void __iomem *regs;
329 unsigned int index;
191 330
192 struct reset_control *rst; 331 struct reset_control *rst;
193 struct clk *clk_parent; 332 struct clk *clk_parent;
@@ -202,6 +341,7 @@ struct tegra_sor {
202 struct drm_info_list *debugfs_files; 341 struct drm_info_list *debugfs_files;
203 342
204 const struct tegra_sor_ops *ops; 343 const struct tegra_sor_ops *ops;
344 enum tegra_io_pad pad;
205 345
206 /* for HDMI 2.0 */ 346 /* for HDMI 2.0 */
207 struct tegra_sor_hdmi_settings *settings; 347 struct tegra_sor_hdmi_settings *settings;
@@ -480,47 +620,6 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
480 return 0; 620 return 0;
481} 621}
482 622
483static void tegra_sor_dp_term_calibrate(struct tegra_sor *sor)
484{
485 u32 mask = 0x08, adj = 0, value;
486
487 /* enable pad calibration logic */
488 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
489 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
490 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
491
492 value = tegra_sor_readl(sor, SOR_PLL1);
493 value |= SOR_PLL1_TMDS_TERM;
494 tegra_sor_writel(sor, value, SOR_PLL1);
495
496 while (mask) {
497 adj |= mask;
498
499 value = tegra_sor_readl(sor, SOR_PLL1);
500 value &= ~SOR_PLL1_TMDS_TERMADJ_MASK;
501 value |= SOR_PLL1_TMDS_TERMADJ(adj);
502 tegra_sor_writel(sor, value, SOR_PLL1);
503
504 usleep_range(100, 200);
505
506 value = tegra_sor_readl(sor, SOR_PLL1);
507 if (value & SOR_PLL1_TERM_COMPOUT)
508 adj &= ~mask;
509
510 mask >>= 1;
511 }
512
513 value = tegra_sor_readl(sor, SOR_PLL1);
514 value &= ~SOR_PLL1_TMDS_TERMADJ_MASK;
515 value |= SOR_PLL1_TMDS_TERMADJ(adj);
516 tegra_sor_writel(sor, value, SOR_PLL1);
517
518 /* disable pad calibration logic */
519 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
520 value |= SOR_DP_PADCTL_PAD_CAL_PD;
521 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
522}
523
524static void tegra_sor_super_update(struct tegra_sor *sor) 623static void tegra_sor_super_update(struct tegra_sor *sor)
525{ 624{
526 tegra_sor_writel(sor, 0, SOR_SUPER_STATE0); 625 tegra_sor_writel(sor, 0, SOR_SUPER_STATE0);
@@ -1217,6 +1316,7 @@ static const struct debugfs_reg32 tegra_sor_regs[] = {
1217 DEBUGFS_REG32(SOR_DP_MN1), 1316 DEBUGFS_REG32(SOR_DP_MN1),
1218 DEBUGFS_REG32(SOR_DP_PADCTL0), 1317 DEBUGFS_REG32(SOR_DP_PADCTL0),
1219 DEBUGFS_REG32(SOR_DP_PADCTL1), 1318 DEBUGFS_REG32(SOR_DP_PADCTL1),
1319 DEBUGFS_REG32(SOR_DP_PADCTL2),
1220 DEBUGFS_REG32(SOR_DP_DEBUG0), 1320 DEBUGFS_REG32(SOR_DP_DEBUG0),
1221 DEBUGFS_REG32(SOR_DP_DEBUG1), 1321 DEBUGFS_REG32(SOR_DP_DEBUG1),
1222 DEBUGFS_REG32(SOR_DP_SPARE0), 1322 DEBUGFS_REG32(SOR_DP_SPARE0),
@@ -1429,7 +1529,7 @@ static void tegra_sor_edp_disable(struct drm_encoder *encoder)
1429 */ 1529 */
1430 if (dc) { 1530 if (dc) {
1431 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 1531 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
1432 value &= ~SOR_ENABLE; 1532 value &= ~SOR_ENABLE(0);
1433 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 1533 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
1434 1534
1435 tegra_dc_commit(dc); 1535 tegra_dc_commit(dc);
@@ -1445,9 +1545,9 @@ static void tegra_sor_edp_disable(struct drm_encoder *encoder)
1445 dev_err(sor->dev, "failed to disable DP: %d\n", err); 1545 dev_err(sor->dev, "failed to disable DP: %d\n", err);
1446 } 1546 }
1447 1547
1448 err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS); 1548 err = tegra_io_pad_power_disable(sor->pad);
1449 if (err < 0) 1549 if (err < 0)
1450 dev_err(sor->dev, "failed to power off I/O rail: %d\n", err); 1550 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
1451 1551
1452 if (output->panel) 1552 if (output->panel)
1453 drm_panel_unprepare(output->panel); 1553 drm_panel_unprepare(output->panel);
@@ -1605,9 +1705,9 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
1605 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 1705 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
1606 1706
1607 /* step 2 */ 1707 /* step 2 */
1608 err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS); 1708 err = tegra_io_pad_power_enable(sor->pad);
1609 if (err < 0) 1709 if (err < 0)
1610 dev_err(sor->dev, "failed to power on I/O rail: %d\n", err); 1710 dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);
1611 1711
1612 usleep_range(5, 100); 1712 usleep_range(5, 100);
1613 1713
@@ -1785,7 +1885,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
1785 tegra_sor_update(sor); 1885 tegra_sor_update(sor);
1786 1886
1787 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 1887 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
1788 value |= SOR_ENABLE; 1888 value |= SOR_ENABLE(0);
1789 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 1889 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
1790 1890
1791 tegra_dc_commit(dc); 1891 tegra_dc_commit(dc);
@@ -1984,8 +2084,12 @@ static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
1984 2084
1985 /* disable display to SOR clock */ 2085 /* disable display to SOR clock */
1986 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 2086 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
1987 value &= ~SOR1_TIMING_CYA; 2087
1988 value &= ~SOR1_ENABLE; 2088 if (!sor->soc->has_nvdisplay)
2089 value &= ~(SOR1_TIMING_CYA | SOR_ENABLE(1));
2090 else
2091 value &= ~SOR_ENABLE(sor->index);
2092
1989 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 2093 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
1990 2094
1991 tegra_dc_commit(dc); 2095 tegra_dc_commit(dc);
@@ -1994,9 +2098,9 @@ static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
1994 if (err < 0) 2098 if (err < 0)
1995 dev_err(sor->dev, "failed to power down SOR: %d\n", err); 2099 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
1996 2100
1997 err = tegra_io_rail_power_off(TEGRA_IO_RAIL_HDMI); 2101 err = tegra_io_pad_power_disable(sor->pad);
1998 if (err < 0) 2102 if (err < 0)
1999 dev_err(sor->dev, "failed to power off HDMI rail: %d\n", err); 2103 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
2000 2104
2001 pm_runtime_put(sor->dev); 2105 pm_runtime_put(sor->dev);
2002} 2106}
@@ -2028,9 +2132,9 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2028 2132
2029 div = clk_get_rate(sor->clk) / 1000000 * 4; 2133 div = clk_get_rate(sor->clk) / 1000000 * 4;
2030 2134
2031 err = tegra_io_rail_power_on(TEGRA_IO_RAIL_HDMI); 2135 err = tegra_io_pad_power_enable(sor->pad);
2032 if (err < 0) 2136 if (err < 0)
2033 dev_err(sor->dev, "failed to power on HDMI rail: %d\n", err); 2137 dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);
2034 2138
2035 usleep_range(20, 100); 2139 usleep_range(20, 100);
2036 2140
@@ -2099,10 +2203,19 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2099 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK; 2203 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK;
2100 tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 2204 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
2101 2205
2206 /* 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
2102 value = tegra_sor_readl(sor, SOR_DP_SPARE0); 2214 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
2103 value |= SOR_DP_SPARE_DISP_VIDEO_PREAMBLE; 2215 value &= ~SOR_DP_SPARE_DISP_VIDEO_PREAMBLE;
2104 value &= ~SOR_DP_SPARE_PANEL_INTERNAL; 2216 value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
2105 value |= SOR_DP_SPARE_SEQ_ENABLE; 2217 value &= ~SOR_DP_SPARE_SEQ_ENABLE;
2218 value &= ~SOR_DP_SPARE_MACRO_SOR_CLK;
2106 tegra_sor_writel(sor, value, SOR_DP_SPARE0); 2219 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
2107 2220
2108 value = SOR_SEQ_CTL_PU_PC(0) | SOR_SEQ_CTL_PU_PC_ALT(0) | 2221 value = SOR_SEQ_CTL_PU_PC(0) | SOR_SEQ_CTL_PU_PC_ALT(0) |
@@ -2114,9 +2227,11 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2114 tegra_sor_writel(sor, value, SOR_SEQ_INST(0)); 2227 tegra_sor_writel(sor, value, SOR_SEQ_INST(0));
2115 tegra_sor_writel(sor, value, SOR_SEQ_INST(8)); 2228 tegra_sor_writel(sor, value, SOR_SEQ_INST(8));
2116 2229
2117 /* program the reference clock */ 2230 if (!sor->soc->has_nvdisplay) {
2118 value = SOR_REFCLK_DIV_INT(div) | SOR_REFCLK_DIV_FRAC(div); 2231 /* program the reference clock */
2119 tegra_sor_writel(sor, value, SOR_REFCLK); 2232 value = SOR_REFCLK_DIV_INT(div) | SOR_REFCLK_DIV_FRAC(div);
2233 tegra_sor_writel(sor, value, SOR_REFCLK);
2234 }
2120 2235
2121 /* XXX not in TRM */ 2236 /* XXX not in TRM */
2122 for (value = 0, i = 0; i < 5; i++) 2237 for (value = 0, i = 0; i < 5; i++)
@@ -2139,13 +2254,16 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2139 return; 2254 return;
2140 } 2255 }
2141 2256
2142 value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
2143 2257
2144 /* XXX is this the proper check? */ 2258 if (!sor->soc->has_nvdisplay) {
2145 if (mode->clock < 75000) 2259 value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
2146 value |= SOR_INPUT_CONTROL_ARM_VIDEO_RANGE_LIMITED; 2260
2261 /* XXX is this the proper check? */
2262 if (mode->clock < 75000)
2263 value |= SOR_INPUT_CONTROL_ARM_VIDEO_RANGE_LIMITED;
2147 2264
2148 tegra_sor_writel(sor, value, SOR_INPUT_CONTROL); 2265 tegra_sor_writel(sor, value, SOR_INPUT_CONTROL);
2266 }
2149 2267
2150 max_ac = ((mode->htotal - mode->hdisplay) - SOR_REKEY - 18) / 32; 2268 max_ac = ((mode->htotal - mode->hdisplay) - SOR_REKEY - 18) / 32;
2151 2269
@@ -2153,20 +2271,23 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2153 SOR_HDMI_CTRL_AUDIO_LAYOUT | SOR_HDMI_CTRL_REKEY(SOR_REKEY); 2271 SOR_HDMI_CTRL_AUDIO_LAYOUT | SOR_HDMI_CTRL_REKEY(SOR_REKEY);
2154 tegra_sor_writel(sor, value, SOR_HDMI_CTRL); 2272 tegra_sor_writel(sor, value, SOR_HDMI_CTRL);
2155 2273
2156 /* H_PULSE2 setup */ 2274 if (!dc->soc->has_nvdisplay) {
2157 pulse_start = h_ref_to_sync + (mode->hsync_end - mode->hsync_start) + 2275 /* H_PULSE2 setup */
2158 (mode->htotal - mode->hsync_end) - 10; 2276 pulse_start = h_ref_to_sync +
2277 (mode->hsync_end - mode->hsync_start) +
2278 (mode->htotal - mode->hsync_end) - 10;
2159 2279
2160 value = PULSE_LAST_END_A | PULSE_QUAL_VACTIVE | 2280 value = PULSE_LAST_END_A | PULSE_QUAL_VACTIVE |
2161 PULSE_POLARITY_HIGH | PULSE_MODE_NORMAL; 2281 PULSE_POLARITY_HIGH | PULSE_MODE_NORMAL;
2162 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL); 2282 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
2163 2283
2164 value = PULSE_END(pulse_start + 8) | PULSE_START(pulse_start); 2284 value = PULSE_END(pulse_start + 8) | PULSE_START(pulse_start);
2165 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A); 2285 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
2166 2286
2167 value = tegra_dc_readl(dc, DC_DISP_DISP_SIGNAL_OPTIONS0); 2287 value = tegra_dc_readl(dc, DC_DISP_DISP_SIGNAL_OPTIONS0);
2168 value |= H_PULSE2_ENABLE; 2288 value |= H_PULSE2_ENABLE;
2169 tegra_dc_writel(dc, value, DC_DISP_DISP_SIGNAL_OPTIONS0); 2289 tegra_dc_writel(dc, value, DC_DISP_DISP_SIGNAL_OPTIONS0);
2290 }
2170 2291
2171 /* infoframe setup */ 2292 /* infoframe setup */
2172 err = tegra_sor_hdmi_setup_avi_infoframe(sor, mode); 2293 err = tegra_sor_hdmi_setup_avi_infoframe(sor, mode);
@@ -2197,49 +2318,66 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2197 2318
2198 value = tegra_sor_readl(sor, sor->soc->regs->pll0); 2319 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
2199 value &= ~SOR_PLL0_ICHPMP_MASK; 2320 value &= ~SOR_PLL0_ICHPMP_MASK;
2321 value &= ~SOR_PLL0_FILTER_MASK;
2200 value &= ~SOR_PLL0_VCOCAP_MASK; 2322 value &= ~SOR_PLL0_VCOCAP_MASK;
2201 value |= SOR_PLL0_ICHPMP(settings->ichpmp); 2323 value |= SOR_PLL0_ICHPMP(settings->ichpmp);
2324 value |= SOR_PLL0_FILTER(settings->filter);
2202 value |= SOR_PLL0_VCOCAP(settings->vcocap); 2325 value |= SOR_PLL0_VCOCAP(settings->vcocap);
2203 tegra_sor_writel(sor, value, sor->soc->regs->pll0); 2326 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
2204 2327
2205 tegra_sor_dp_term_calibrate(sor); 2328 /* XXX not in TRM */
2206
2207 value = tegra_sor_readl(sor, sor->soc->regs->pll1); 2329 value = tegra_sor_readl(sor, sor->soc->regs->pll1);
2208 value &= ~SOR_PLL1_LOADADJ_MASK; 2330 value &= ~SOR_PLL1_LOADADJ_MASK;
2331 value &= ~SOR_PLL1_TMDS_TERMADJ_MASK;
2209 value |= SOR_PLL1_LOADADJ(settings->loadadj); 2332 value |= SOR_PLL1_LOADADJ(settings->loadadj);
2333 value |= SOR_PLL1_TMDS_TERMADJ(settings->tmds_termadj);
2334 value |= SOR_PLL1_TMDS_TERM;
2210 tegra_sor_writel(sor, value, sor->soc->regs->pll1); 2335 tegra_sor_writel(sor, value, sor->soc->regs->pll1);
2211 2336
2212 value = tegra_sor_readl(sor, sor->soc->regs->pll3); 2337 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
2338 value &= ~SOR_PLL3_BG_TEMP_COEF_MASK;
2213 value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK; 2339 value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK;
2214 value |= SOR_PLL3_BG_VREF_LEVEL(settings->bg_vref); 2340 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);
2215 tegra_sor_writel(sor, value, sor->soc->regs->pll3); 2346 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
2216 2347
2217 value = settings->drive_current[0] << 24 | 2348 value = settings->drive_current[3] << 24 |
2218 settings->drive_current[1] << 16 | 2349 settings->drive_current[2] << 16 |
2219 settings->drive_current[2] << 8 | 2350 settings->drive_current[1] << 8 |
2220 settings->drive_current[3] << 0; 2351 settings->drive_current[0] << 0;
2221 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0); 2352 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0);
2222 2353
2223 value = settings->preemphasis[0] << 24 | 2354 value = settings->preemphasis[3] << 24 |
2224 settings->preemphasis[1] << 16 | 2355 settings->preemphasis[2] << 16 |
2225 settings->preemphasis[2] << 8 | 2356 settings->preemphasis[1] << 8 |
2226 settings->preemphasis[3] << 0; 2357 settings->preemphasis[0] << 0;
2227 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0); 2358 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
2228 2359
2229 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 2360 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
2230 value &= ~SOR_DP_PADCTL_TX_PU_MASK; 2361 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
2231 value |= SOR_DP_PADCTL_TX_PU_ENABLE; 2362 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
2232 value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu); 2363 value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu_value);
2233 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 2364 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
2234 2365
2366 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
2235 /* power down pad calibration */ 2371 /* power down pad calibration */
2236 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 2372 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
2237 value |= SOR_DP_PADCTL_PAD_CAL_PD; 2373 value |= SOR_DP_PADCTL_PAD_CAL_PD;
2238 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 2374 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
2239 2375
2240 /* miscellaneous display controller settings */ 2376 if (!dc->soc->has_nvdisplay) {
2241 value = VSYNC_H_POSITION(1); 2377 /* miscellaneous display controller settings */
2242 tegra_dc_writel(dc, value, DC_DISP_DISP_TIMING_OPTIONS); 2378 value = VSYNC_H_POSITION(1);
2379 tegra_dc_writel(dc, value, DC_DISP_DISP_TIMING_OPTIONS);
2380 }
2243 2381
2244 value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL); 2382 value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
2245 value &= ~DITHER_CONTROL_MASK; 2383 value &= ~DITHER_CONTROL_MASK;
@@ -2254,6 +2392,14 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2254 value |= BASE_COLOR_SIZE_888; 2392 value |= BASE_COLOR_SIZE_888;
2255 break; 2393 break;
2256 2394
2395 case 10:
2396 value |= BASE_COLOR_SIZE_101010;
2397 break;
2398
2399 case 12:
2400 value |= BASE_COLOR_SIZE_121212;
2401 break;
2402
2257 default: 2403 default:
2258 WARN(1, "%u bits-per-color not supported\n", state->bpc); 2404 WARN(1, "%u bits-per-color not supported\n", state->bpc);
2259 value |= BASE_COLOR_SIZE_888; 2405 value |= BASE_COLOR_SIZE_888;
@@ -2262,6 +2408,12 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2262 2408
2263 tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL); 2409 tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
2264 2410
2411 /* 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
2265 err = tegra_sor_power_up(sor, 250); 2417 err = tegra_sor_power_up(sor, 250);
2266 if (err < 0) 2418 if (err < 0)
2267 dev_err(sor->dev, "failed to power up SOR: %d\n", err); 2419 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
@@ -2282,15 +2434,32 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2282 2434
2283 tegra_sor_update(sor); 2435 tegra_sor_update(sor);
2284 2436
2437 /* 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
2285 err = tegra_sor_attach(sor); 2442 err = tegra_sor_attach(sor);
2286 if (err < 0) 2443 if (err < 0)
2287 dev_err(sor->dev, "failed to attach SOR: %d\n", err); 2444 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
2288 2445
2289 /* enable display to SOR clock and generate HDMI preamble */ 2446 /* enable display to SOR clock and generate HDMI preamble */
2290 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 2447 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
2291 value |= SOR1_ENABLE | SOR1_TIMING_CYA; 2448
2449 if (!sor->soc->has_nvdisplay)
2450 value |= SOR_ENABLE(1) | SOR1_TIMING_CYA;
2451 else
2452 value |= SOR_ENABLE(sor->index);
2453
2292 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 2454 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
2293 2455
2456 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
2294 tegra_dc_commit(dc); 2463 tegra_dc_commit(dc);
2295 2464
2296 err = tegra_sor_wakeup(sor); 2465 err = tegra_sor_wakeup(sor);
@@ -2356,7 +2525,7 @@ static int tegra_sor_init(struct host1x_client *client)
2356 return err; 2525 return err;
2357 } 2526 }
2358 2527
2359 sor->output.encoder.possible_crtcs = 0x3; 2528 tegra_output_find_possible_crtcs(&sor->output, drm);
2360 2529
2361 if (sor->aux) { 2530 if (sor->aux) {
2362 err = drm_dp_aux_attach(sor->aux, &sor->output); 2531 err = drm_dp_aux_attach(sor->aux, &sor->output);
@@ -2526,6 +2695,7 @@ static const struct tegra_sor_soc tegra124_sor = {
2526 .supports_hdmi = false, 2695 .supports_hdmi = false,
2527 .supports_dp = false, 2696 .supports_dp = false,
2528 .regs = &tegra124_sor_regs, 2697 .regs = &tegra124_sor_regs,
2698 .has_nvdisplay = false,
2529 .xbar_cfg = tegra124_sor_xbar_cfg, 2699 .xbar_cfg = tegra124_sor_xbar_cfg,
2530}; 2700};
2531 2701
@@ -2550,6 +2720,7 @@ static const struct tegra_sor_soc tegra210_sor = {
2550 .supports_hdmi = false, 2720 .supports_hdmi = false,
2551 .supports_dp = false, 2721 .supports_dp = false,
2552 .regs = &tegra210_sor_regs, 2722 .regs = &tegra210_sor_regs,
2723 .has_nvdisplay = false,
2553 .xbar_cfg = tegra124_sor_xbar_cfg, 2724 .xbar_cfg = tegra124_sor_xbar_cfg,
2554}; 2725};
2555 2726
@@ -2564,6 +2735,7 @@ static const struct tegra_sor_soc tegra210_sor1 = {
2564 .supports_dp = true, 2735 .supports_dp = true,
2565 2736
2566 .regs = &tegra210_sor_regs, 2737 .regs = &tegra210_sor_regs,
2738 .has_nvdisplay = false,
2567 2739
2568 .num_settings = ARRAY_SIZE(tegra210_sor_hdmi_defaults), 2740 .num_settings = ARRAY_SIZE(tegra210_sor_hdmi_defaults),
2569 .settings = tegra210_sor_hdmi_defaults, 2741 .settings = tegra210_sor_hdmi_defaults,
@@ -2571,7 +2743,51 @@ static const struct tegra_sor_soc tegra210_sor1 = {
2571 .xbar_cfg = tegra210_sor_xbar_cfg, 2743 .xbar_cfg = tegra210_sor_xbar_cfg,
2572}; 2744};
2573 2745
2746static 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
2574static const struct of_device_id tegra_sor_of_match[] = { 2788static const struct of_device_id tegra_sor_of_match[] = {
2789 { .compatible = "nvidia,tegra186-sor1", .data = &tegra186_sor1 },
2790 { .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor },
2575 { .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 }, 2791 { .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 },
2576 { .compatible = "nvidia,tegra210-sor", .data = &tegra210_sor }, 2792 { .compatible = "nvidia,tegra210-sor", .data = &tegra210_sor },
2577 { .compatible = "nvidia,tegra124-sor", .data = &tegra124_sor }, 2793 { .compatible = "nvidia,tegra124-sor", .data = &tegra124_sor },
@@ -2579,6 +2795,29 @@ static const struct of_device_id tegra_sor_of_match[] = {
2579}; 2795};
2580MODULE_DEVICE_TABLE(of, tegra_sor_of_match); 2796MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
2581 2797
2798static 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
2582static int tegra_sor_probe(struct platform_device *pdev) 2821static int tegra_sor_probe(struct platform_device *pdev)
2583{ 2822{
2584 struct device_node *np; 2823 struct device_node *np;
@@ -2614,6 +2853,7 @@ static int tegra_sor_probe(struct platform_device *pdev)
2614 if (!sor->aux) { 2853 if (!sor->aux) {
2615 if (sor->soc->supports_hdmi) { 2854 if (sor->soc->supports_hdmi) {
2616 sor->ops = &tegra_sor_hdmi_ops; 2855 sor->ops = &tegra_sor_hdmi_ops;
2856 sor->pad = TEGRA_IO_PAD_HDMI;
2617 } else if (sor->soc->supports_lvds) { 2857 } else if (sor->soc->supports_lvds) {
2618 dev_err(&pdev->dev, "LVDS not supported yet\n"); 2858 dev_err(&pdev->dev, "LVDS not supported yet\n");
2619 return -ENODEV; 2859 return -ENODEV;
@@ -2624,6 +2864,7 @@ static int tegra_sor_probe(struct platform_device *pdev)
2624 } else { 2864 } else {
2625 if (sor->soc->supports_edp) { 2865 if (sor->soc->supports_edp) {
2626 sor->ops = &tegra_sor_edp_ops; 2866 sor->ops = &tegra_sor_edp_ops;
2867 sor->pad = TEGRA_IO_PAD_LVDS;
2627 } else if (sor->soc->supports_dp) { 2868 } else if (sor->soc->supports_dp) {
2628 dev_err(&pdev->dev, "DisplayPort not supported yet\n"); 2869 dev_err(&pdev->dev, "DisplayPort not supported yet\n");
2629 return -ENODEV; 2870 return -ENODEV;
@@ -2633,6 +2874,10 @@ static int tegra_sor_probe(struct platform_device *pdev)
2633 } 2874 }
2634 } 2875 }
2635 2876
2877 err = tegra_sor_parse_dt(sor);
2878 if (err < 0)
2879 return err;
2880
2636 err = tegra_output_probe(&sor->output); 2881 err = tegra_output_probe(&sor->output);
2637 if (err < 0) { 2882 if (err < 0) {
2638 dev_err(&pdev->dev, "failed to probe output: %d\n", err); 2883 dev_err(&pdev->dev, "failed to probe output: %d\n", err);
diff --git a/drivers/gpu/drm/tegra/sor.h b/drivers/gpu/drm/tegra/sor.h
index 865c73b48968..e85ffc8d98e4 100644
--- a/drivers/gpu/drm/tegra/sor.h
+++ b/drivers/gpu/drm/tegra/sor.h
@@ -89,6 +89,8 @@
89#define SOR_PLL0 0x17 89#define SOR_PLL0 0x17
90#define SOR_PLL0_ICHPMP_MASK (0xf << 24) 90#define SOR_PLL0_ICHPMP_MASK (0xf << 24)
91#define SOR_PLL0_ICHPMP(x) (((x) & 0xf) << 24) 91#define SOR_PLL0_ICHPMP(x) (((x) & 0xf) << 24)
92#define SOR_PLL0_FILTER_MASK (0xf << 16)
93#define SOR_PLL0_FILTER(x) (((x) & 0xf) << 16)
92#define SOR_PLL0_VCOCAP_MASK (0xf << 8) 94#define SOR_PLL0_VCOCAP_MASK (0xf << 8)
93#define SOR_PLL0_VCOCAP(x) (((x) & 0xf) << 8) 95#define SOR_PLL0_VCOCAP(x) (((x) & 0xf) << 8)
94#define SOR_PLL0_VCOCAP_RST SOR_PLL0_VCOCAP(3) 96#define SOR_PLL0_VCOCAP_RST SOR_PLL0_VCOCAP(3)
@@ -122,10 +124,16 @@
122#define SOR_PLL2_SEQ_PLL_PULLDOWN (1 << 16) 124#define SOR_PLL2_SEQ_PLL_PULLDOWN (1 << 16)
123 125
124#define SOR_PLL3 0x1a 126#define SOR_PLL3 0x1a
127#define SOR_PLL3_BG_TEMP_COEF_MASK (0xf << 28)
128#define SOR_PLL3_BG_TEMP_COEF(x) (((x) & 0xf) << 28)
125#define SOR_PLL3_BG_VREF_LEVEL_MASK (0xf << 24) 129#define SOR_PLL3_BG_VREF_LEVEL_MASK (0xf << 24)
126#define SOR_PLL3_BG_VREF_LEVEL(x) (((x) & 0xf) << 24) 130#define SOR_PLL3_BG_VREF_LEVEL(x) (((x) & 0xf) << 24)
127#define SOR_PLL3_PLL_VDD_MODE_1V8 (0 << 13) 131#define SOR_PLL3_PLL_VDD_MODE_1V8 (0 << 13)
128#define SOR_PLL3_PLL_VDD_MODE_3V3 (1 << 13) 132#define SOR_PLL3_PLL_VDD_MODE_3V3 (1 << 13)
133#define SOR_PLL3_AVDD10_LEVEL_MASK (0xf << 8)
134#define SOR_PLL3_AVDD10_LEVEL(x) (((x) & 0xf) << 8)
135#define SOR_PLL3_AVDD14_LEVEL_MASK (0xf << 4)
136#define SOR_PLL3_AVDD14_LEVEL(x) (((x) & 0xf) << 4)
129 137
130#define SOR_CSTM 0x1b 138#define SOR_CSTM 0x1b
131#define SOR_CSTM_ROTCLK_MASK (0xf << 24) 139#define SOR_CSTM_ROTCLK_MASK (0xf << 24)
@@ -334,6 +342,10 @@
334#define SOR_DP_LQ_CSTM1 0x70 342#define SOR_DP_LQ_CSTM1 0x70
335#define SOR_DP_LQ_CSTM2 0x71 343#define SOR_DP_LQ_CSTM2 0x71
336 344
345#define SOR_DP_PADCTL2 0x73
346#define SOR_DP_PADCTL_SPAREPLL_MASK (0xff << 24)
347#define SOR_DP_PADCTL_SPAREPLL(x) (((x) & 0xff) << 24)
348
337#define SOR_HDMI_AUDIO_INFOFRAME_CTRL 0x9a 349#define SOR_HDMI_AUDIO_INFOFRAME_CTRL 0x9a
338#define SOR_HDMI_AUDIO_INFOFRAME_STATUS 0x9b 350#define SOR_HDMI_AUDIO_INFOFRAME_STATUS 0x9b
339#define SOR_HDMI_AUDIO_INFOFRAME_HEADER 0x9c 351#define SOR_HDMI_AUDIO_INFOFRAME_HEADER 0x9c