1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2012 Avionic Design GmbH |
4 | * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. |
5 | */ |
6 | |
7 | #include <linux/clk.h> |
8 | #include <linux/debugfs.h> |
9 | #include <linux/delay.h> |
10 | #include <linux/hdmi.h> |
11 | #include <linux/math64.h> |
12 | #include <linux/module.h> |
13 | #include <linux/of.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/pm_opp.h> |
16 | #include <linux/pm_runtime.h> |
17 | #include <linux/regulator/consumer.h> |
18 | #include <linux/reset.h> |
19 | |
20 | #include <soc/tegra/common.h> |
21 | #include <sound/hdmi-codec.h> |
22 | |
23 | #include <drm/drm_bridge_connector.h> |
24 | #include <drm/drm_atomic_helper.h> |
25 | #include <drm/drm_crtc.h> |
26 | #include <drm/drm_debugfs.h> |
27 | #include <drm/drm_file.h> |
28 | #include <drm/drm_fourcc.h> |
29 | #include <drm/drm_probe_helper.h> |
30 | #include <drm/drm_simple_kms_helper.h> |
31 | |
32 | #include "hda.h" |
33 | #include "hdmi.h" |
34 | #include "drm.h" |
35 | #include "dc.h" |
36 | #include "trace.h" |
37 | |
38 | #define HDMI_ELD_BUFFER_SIZE 96 |
39 | |
40 | struct tmds_config { |
41 | unsigned int pclk; |
42 | u32 pll0; |
43 | u32 pll1; |
44 | u32 pe_current; |
45 | u32 drive_current; |
46 | u32 peak_current; |
47 | }; |
48 | |
49 | struct tegra_hdmi_config { |
50 | const struct tmds_config *tmds; |
51 | unsigned int num_tmds; |
52 | |
53 | unsigned long fuse_override_offset; |
54 | u32 fuse_override_value; |
55 | |
56 | bool has_sor_io_peak_current; |
57 | bool has_hda; |
58 | bool has_hbr; |
59 | }; |
60 | |
61 | struct tegra_hdmi { |
62 | struct host1x_client client; |
63 | struct tegra_output output; |
64 | struct device *dev; |
65 | |
66 | struct regulator *hdmi; |
67 | struct regulator *pll; |
68 | struct regulator *vdd; |
69 | |
70 | void __iomem *regs; |
71 | unsigned int irq; |
72 | |
73 | struct clk *clk_parent; |
74 | struct clk *clk; |
75 | struct reset_control *rst; |
76 | |
77 | const struct tegra_hdmi_config *config; |
78 | |
79 | unsigned int audio_source; |
80 | struct tegra_hda_format format; |
81 | |
82 | unsigned int pixel_clock; |
83 | bool stereo; |
84 | bool dvi; |
85 | |
86 | struct drm_info_list *debugfs_files; |
87 | |
88 | struct platform_device *audio_pdev; |
89 | struct mutex audio_lock; |
90 | }; |
91 | |
92 | static inline struct tegra_hdmi * |
93 | host1x_client_to_hdmi(struct host1x_client *client) |
94 | { |
95 | return container_of(client, struct tegra_hdmi, client); |
96 | } |
97 | |
98 | static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output) |
99 | { |
100 | return container_of(output, struct tegra_hdmi, output); |
101 | } |
102 | |
103 | #define HDMI_AUDIOCLK_FREQ 216000000 |
104 | #define HDMI_REKEY_DEFAULT 56 |
105 | |
106 | enum { |
107 | AUTO = 0, |
108 | SPDIF, |
109 | HDA, |
110 | }; |
111 | |
112 | static inline u32 tegra_hdmi_readl(struct tegra_hdmi *hdmi, |
113 | unsigned int offset) |
114 | { |
115 | u32 value = readl(addr: hdmi->regs + (offset << 2)); |
116 | |
117 | trace_hdmi_readl(dev: hdmi->dev, offset, value); |
118 | |
119 | return value; |
120 | } |
121 | |
122 | static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, u32 value, |
123 | unsigned int offset) |
124 | { |
125 | trace_hdmi_writel(dev: hdmi->dev, offset, value); |
126 | writel(val: value, addr: hdmi->regs + (offset << 2)); |
127 | } |
128 | |
129 | struct tegra_hdmi_audio_config { |
130 | unsigned int n; |
131 | unsigned int cts; |
132 | unsigned int aval; |
133 | }; |
134 | |
135 | static const struct tmds_config tegra20_tmds_config[] = { |
136 | { /* slow pixel clock modes */ |
137 | .pclk = 27000000, |
138 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | |
139 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) | |
140 | SOR_PLL_TX_REG_LOAD(3), |
141 | .pll1 = SOR_PLL_TMDS_TERM_ENABLE, |
142 | .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) | |
143 | PE_CURRENT1(PE_CURRENT_0_0_mA) | |
144 | PE_CURRENT2(PE_CURRENT_0_0_mA) | |
145 | PE_CURRENT3(PE_CURRENT_0_0_mA), |
146 | .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) | |
147 | DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | |
148 | DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | |
149 | DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), |
150 | }, |
151 | { /* high pixel clock modes */ |
152 | .pclk = UINT_MAX, |
153 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | |
154 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | |
155 | SOR_PLL_TX_REG_LOAD(3), |
156 | .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, |
157 | .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) | |
158 | PE_CURRENT1(PE_CURRENT_6_0_mA) | |
159 | PE_CURRENT2(PE_CURRENT_6_0_mA) | |
160 | PE_CURRENT3(PE_CURRENT_6_0_mA), |
161 | .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) | |
162 | DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | |
163 | DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | |
164 | DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), |
165 | }, |
166 | }; |
167 | |
168 | static const struct tmds_config tegra30_tmds_config[] = { |
169 | { /* 480p modes */ |
170 | .pclk = 27000000, |
171 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | |
172 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) | |
173 | SOR_PLL_TX_REG_LOAD(0), |
174 | .pll1 = SOR_PLL_TMDS_TERM_ENABLE, |
175 | .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) | |
176 | PE_CURRENT1(PE_CURRENT_0_0_mA) | |
177 | PE_CURRENT2(PE_CURRENT_0_0_mA) | |
178 | PE_CURRENT3(PE_CURRENT_0_0_mA), |
179 | .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | |
180 | DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | |
181 | DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | |
182 | DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), |
183 | }, { /* 720p modes */ |
184 | .pclk = 74250000, |
185 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | |
186 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | |
187 | SOR_PLL_TX_REG_LOAD(0), |
188 | .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, |
189 | .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) | |
190 | PE_CURRENT1(PE_CURRENT_5_0_mA) | |
191 | PE_CURRENT2(PE_CURRENT_5_0_mA) | |
192 | PE_CURRENT3(PE_CURRENT_5_0_mA), |
193 | .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | |
194 | DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | |
195 | DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | |
196 | DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), |
197 | }, { /* 1080p modes */ |
198 | .pclk = UINT_MAX, |
199 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | |
200 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) | |
201 | SOR_PLL_TX_REG_LOAD(0), |
202 | .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, |
203 | .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) | |
204 | PE_CURRENT1(PE_CURRENT_5_0_mA) | |
205 | PE_CURRENT2(PE_CURRENT_5_0_mA) | |
206 | PE_CURRENT3(PE_CURRENT_5_0_mA), |
207 | .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | |
208 | DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | |
209 | DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | |
210 | DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), |
211 | }, |
212 | }; |
213 | |
214 | static const struct tmds_config tegra114_tmds_config[] = { |
215 | { /* 480p/576p / 25.2MHz/27MHz modes */ |
216 | .pclk = 27000000, |
217 | .pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) | |
218 | SOR_PLL_VCOCAP(0) | SOR_PLL_RESISTORSEL, |
219 | .pll1 = SOR_PLL_LOADADJ(3) | SOR_PLL_TMDS_TERMADJ(0), |
220 | .pe_current = PE_CURRENT0(PE_CURRENT_0_mA_T114) | |
221 | PE_CURRENT1(PE_CURRENT_0_mA_T114) | |
222 | PE_CURRENT2(PE_CURRENT_0_mA_T114) | |
223 | PE_CURRENT3(PE_CURRENT_0_mA_T114), |
224 | .drive_current = |
225 | DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_10_400_mA_T114) | |
226 | DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_10_400_mA_T114) | |
227 | DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_10_400_mA_T114) | |
228 | DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_10_400_mA_T114), |
229 | .peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) | |
230 | PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) | |
231 | PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) | |
232 | PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA), |
233 | }, { /* 720p / 74.25MHz modes */ |
234 | .pclk = 74250000, |
235 | .pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) | |
236 | SOR_PLL_VCOCAP(1) | SOR_PLL_RESISTORSEL, |
237 | .pll1 = SOR_PLL_PE_EN | SOR_PLL_LOADADJ(3) | |
238 | SOR_PLL_TMDS_TERMADJ(0), |
239 | .pe_current = PE_CURRENT0(PE_CURRENT_15_mA_T114) | |
240 | PE_CURRENT1(PE_CURRENT_15_mA_T114) | |
241 | PE_CURRENT2(PE_CURRENT_15_mA_T114) | |
242 | PE_CURRENT3(PE_CURRENT_15_mA_T114), |
243 | .drive_current = |
244 | DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_10_400_mA_T114) | |
245 | DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_10_400_mA_T114) | |
246 | DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_10_400_mA_T114) | |
247 | DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_10_400_mA_T114), |
248 | .peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) | |
249 | PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) | |
250 | PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) | |
251 | PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA), |
252 | }, { /* 1080p / 148.5MHz modes */ |
253 | .pclk = 148500000, |
254 | .pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) | |
255 | SOR_PLL_VCOCAP(3) | SOR_PLL_RESISTORSEL, |
256 | .pll1 = SOR_PLL_PE_EN | SOR_PLL_LOADADJ(3) | |
257 | SOR_PLL_TMDS_TERMADJ(0), |
258 | .pe_current = PE_CURRENT0(PE_CURRENT_10_mA_T114) | |
259 | PE_CURRENT1(PE_CURRENT_10_mA_T114) | |
260 | PE_CURRENT2(PE_CURRENT_10_mA_T114) | |
261 | PE_CURRENT3(PE_CURRENT_10_mA_T114), |
262 | .drive_current = |
263 | DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_12_400_mA_T114) | |
264 | DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_12_400_mA_T114) | |
265 | DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_12_400_mA_T114) | |
266 | DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_12_400_mA_T114), |
267 | .peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) | |
268 | PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) | |
269 | PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) | |
270 | PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA), |
271 | }, { /* 225/297MHz modes */ |
272 | .pclk = UINT_MAX, |
273 | .pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) | |
274 | SOR_PLL_VCOCAP(0xf) | SOR_PLL_RESISTORSEL, |
275 | .pll1 = SOR_PLL_LOADADJ(3) | SOR_PLL_TMDS_TERMADJ(7) |
276 | | SOR_PLL_TMDS_TERM_ENABLE, |
277 | .pe_current = PE_CURRENT0(PE_CURRENT_0_mA_T114) | |
278 | PE_CURRENT1(PE_CURRENT_0_mA_T114) | |
279 | PE_CURRENT2(PE_CURRENT_0_mA_T114) | |
280 | PE_CURRENT3(PE_CURRENT_0_mA_T114), |
281 | .drive_current = |
282 | DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_25_200_mA_T114) | |
283 | DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_25_200_mA_T114) | |
284 | DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_25_200_mA_T114) | |
285 | DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_19_200_mA_T114), |
286 | .peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_3_000_mA) | |
287 | PEAK_CURRENT_LANE1(PEAK_CURRENT_3_000_mA) | |
288 | PEAK_CURRENT_LANE2(PEAK_CURRENT_3_000_mA) | |
289 | PEAK_CURRENT_LANE3(PEAK_CURRENT_0_800_mA), |
290 | }, |
291 | }; |
292 | |
293 | static const struct tmds_config tegra124_tmds_config[] = { |
294 | { /* 480p/576p / 25.2MHz/27MHz modes */ |
295 | .pclk = 27000000, |
296 | .pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) | |
297 | SOR_PLL_VCOCAP(0) | SOR_PLL_RESISTORSEL, |
298 | .pll1 = SOR_PLL_LOADADJ(3) | SOR_PLL_TMDS_TERMADJ(0), |
299 | .pe_current = PE_CURRENT0(PE_CURRENT_0_mA_T114) | |
300 | PE_CURRENT1(PE_CURRENT_0_mA_T114) | |
301 | PE_CURRENT2(PE_CURRENT_0_mA_T114) | |
302 | PE_CURRENT3(PE_CURRENT_0_mA_T114), |
303 | .drive_current = |
304 | DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_10_400_mA_T114) | |
305 | DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_10_400_mA_T114) | |
306 | DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_10_400_mA_T114) | |
307 | DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_10_400_mA_T114), |
308 | .peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) | |
309 | PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) | |
310 | PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) | |
311 | PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA), |
312 | }, { /* 720p / 74.25MHz modes */ |
313 | .pclk = 74250000, |
314 | .pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) | |
315 | SOR_PLL_VCOCAP(1) | SOR_PLL_RESISTORSEL, |
316 | .pll1 = SOR_PLL_PE_EN | SOR_PLL_LOADADJ(3) | |
317 | SOR_PLL_TMDS_TERMADJ(0), |
318 | .pe_current = PE_CURRENT0(PE_CURRENT_15_mA_T114) | |
319 | PE_CURRENT1(PE_CURRENT_15_mA_T114) | |
320 | PE_CURRENT2(PE_CURRENT_15_mA_T114) | |
321 | PE_CURRENT3(PE_CURRENT_15_mA_T114), |
322 | .drive_current = |
323 | DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_10_400_mA_T114) | |
324 | DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_10_400_mA_T114) | |
325 | DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_10_400_mA_T114) | |
326 | DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_10_400_mA_T114), |
327 | .peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) | |
328 | PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) | |
329 | PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) | |
330 | PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA), |
331 | }, { /* 1080p / 148.5MHz modes */ |
332 | .pclk = 148500000, |
333 | .pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) | |
334 | SOR_PLL_VCOCAP(3) | SOR_PLL_RESISTORSEL, |
335 | .pll1 = SOR_PLL_PE_EN | SOR_PLL_LOADADJ(3) | |
336 | SOR_PLL_TMDS_TERMADJ(0), |
337 | .pe_current = PE_CURRENT0(PE_CURRENT_10_mA_T114) | |
338 | PE_CURRENT1(PE_CURRENT_10_mA_T114) | |
339 | PE_CURRENT2(PE_CURRENT_10_mA_T114) | |
340 | PE_CURRENT3(PE_CURRENT_10_mA_T114), |
341 | .drive_current = |
342 | DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_12_400_mA_T114) | |
343 | DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_12_400_mA_T114) | |
344 | DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_12_400_mA_T114) | |
345 | DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_12_400_mA_T114), |
346 | .peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_0_000_mA) | |
347 | PEAK_CURRENT_LANE1(PEAK_CURRENT_0_000_mA) | |
348 | PEAK_CURRENT_LANE2(PEAK_CURRENT_0_000_mA) | |
349 | PEAK_CURRENT_LANE3(PEAK_CURRENT_0_000_mA), |
350 | }, { /* 225/297MHz modes */ |
351 | .pclk = UINT_MAX, |
352 | .pll0 = SOR_PLL_ICHPMP(1) | SOR_PLL_BG_V17_S(3) | |
353 | SOR_PLL_VCOCAP(0xf) | SOR_PLL_RESISTORSEL, |
354 | .pll1 = SOR_PLL_LOADADJ(3) | SOR_PLL_TMDS_TERMADJ(7) |
355 | | SOR_PLL_TMDS_TERM_ENABLE, |
356 | .pe_current = PE_CURRENT0(PE_CURRENT_0_mA_T114) | |
357 | PE_CURRENT1(PE_CURRENT_0_mA_T114) | |
358 | PE_CURRENT2(PE_CURRENT_0_mA_T114) | |
359 | PE_CURRENT3(PE_CURRENT_0_mA_T114), |
360 | .drive_current = |
361 | DRIVE_CURRENT_LANE0_T114(DRIVE_CURRENT_25_200_mA_T114) | |
362 | DRIVE_CURRENT_LANE1_T114(DRIVE_CURRENT_25_200_mA_T114) | |
363 | DRIVE_CURRENT_LANE2_T114(DRIVE_CURRENT_25_200_mA_T114) | |
364 | DRIVE_CURRENT_LANE3_T114(DRIVE_CURRENT_19_200_mA_T114), |
365 | .peak_current = PEAK_CURRENT_LANE0(PEAK_CURRENT_3_000_mA) | |
366 | PEAK_CURRENT_LANE1(PEAK_CURRENT_3_000_mA) | |
367 | PEAK_CURRENT_LANE2(PEAK_CURRENT_3_000_mA) | |
368 | PEAK_CURRENT_LANE3(PEAK_CURRENT_0_800_mA), |
369 | }, |
370 | }; |
371 | |
372 | static void tegra_hdmi_audio_lock(struct tegra_hdmi *hdmi) |
373 | { |
374 | mutex_lock(&hdmi->audio_lock); |
375 | disable_irq(irq: hdmi->irq); |
376 | } |
377 | |
378 | static void tegra_hdmi_audio_unlock(struct tegra_hdmi *hdmi) |
379 | { |
380 | enable_irq(irq: hdmi->irq); |
381 | mutex_unlock(lock: &hdmi->audio_lock); |
382 | } |
383 | |
384 | static int |
385 | tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pix_clock, |
386 | struct tegra_hdmi_audio_config *config) |
387 | { |
388 | const unsigned int afreq = 128 * audio_freq; |
389 | const unsigned int min_n = afreq / 1500; |
390 | const unsigned int max_n = afreq / 300; |
391 | const unsigned int ideal_n = afreq / 1000; |
392 | int64_t min_err = (uint64_t)-1 >> 1; |
393 | unsigned int min_delta = -1; |
394 | int n; |
395 | |
396 | memset(config, 0, sizeof(*config)); |
397 | config->n = -1; |
398 | |
399 | for (n = min_n; n <= max_n; n++) { |
400 | uint64_t cts_f, aval_f; |
401 | unsigned int delta; |
402 | int64_t cts, err; |
403 | |
404 | /* compute aval in 48.16 fixed point */ |
405 | aval_f = ((int64_t)24000000 << 16) * n; |
406 | do_div(aval_f, afreq); |
407 | /* It should round without any rest */ |
408 | if (aval_f & 0xFFFF) |
409 | continue; |
410 | |
411 | /* Compute cts in 48.16 fixed point */ |
412 | cts_f = ((int64_t)pix_clock << 16) * n; |
413 | do_div(cts_f, afreq); |
414 | /* Round it to the nearest integer */ |
415 | cts = (cts_f & ~0xFFFF) + ((cts_f & BIT(15)) << 1); |
416 | |
417 | delta = abs(n - ideal_n); |
418 | |
419 | /* Compute the absolute error */ |
420 | err = abs((int64_t)cts_f - cts); |
421 | if (err < min_err || (err == min_err && delta < min_delta)) { |
422 | config->n = n; |
423 | config->cts = cts >> 16; |
424 | config->aval = aval_f >> 16; |
425 | min_delta = delta; |
426 | min_err = err; |
427 | } |
428 | } |
429 | |
430 | return config->n != -1 ? 0 : -EINVAL; |
431 | } |
432 | |
433 | static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi) |
434 | { |
435 | const unsigned int freqs[] = { |
436 | 32000, 44100, 48000, 88200, 96000, 176400, 192000 |
437 | }; |
438 | unsigned int i; |
439 | |
440 | for (i = 0; i < ARRAY_SIZE(freqs); i++) { |
441 | unsigned int f = freqs[i]; |
442 | unsigned int eight_half; |
443 | unsigned int delta; |
444 | u32 value; |
445 | |
446 | if (f > 96000) |
447 | delta = 2; |
448 | else if (f > 48000) |
449 | delta = 6; |
450 | else |
451 | delta = 9; |
452 | |
453 | eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128); |
454 | value = AUDIO_FS_LOW(eight_half - delta) | |
455 | AUDIO_FS_HIGH(eight_half + delta); |
456 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i)); |
457 | } |
458 | } |
459 | |
460 | static void tegra_hdmi_write_aval(struct tegra_hdmi *hdmi, u32 value) |
461 | { |
462 | static const struct { |
463 | unsigned int sample_rate; |
464 | unsigned int offset; |
465 | } regs[] = { |
466 | { 32000, HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320 }, |
467 | { 44100, HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441 }, |
468 | { 48000, HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480 }, |
469 | { 88200, HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882 }, |
470 | { 96000, HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960 }, |
471 | { 176400, HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764 }, |
472 | { 192000, HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920 }, |
473 | }; |
474 | unsigned int i; |
475 | |
476 | for (i = 0; i < ARRAY_SIZE(regs); i++) { |
477 | if (regs[i].sample_rate == hdmi->format.sample_rate) { |
478 | tegra_hdmi_writel(hdmi, value, offset: regs[i].offset); |
479 | break; |
480 | } |
481 | } |
482 | } |
483 | |
484 | static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi) |
485 | { |
486 | struct tegra_hdmi_audio_config config; |
487 | u32 source, value; |
488 | int err; |
489 | |
490 | switch (hdmi->audio_source) { |
491 | case HDA: |
492 | if (hdmi->config->has_hda) |
493 | source = SOR_AUDIO_CNTRL0_SOURCE_SELECT_HDAL; |
494 | else |
495 | return -EINVAL; |
496 | |
497 | break; |
498 | |
499 | case SPDIF: |
500 | if (hdmi->config->has_hda) |
501 | source = SOR_AUDIO_CNTRL0_SOURCE_SELECT_SPDIF; |
502 | else |
503 | source = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF; |
504 | break; |
505 | |
506 | default: |
507 | if (hdmi->config->has_hda) |
508 | source = SOR_AUDIO_CNTRL0_SOURCE_SELECT_AUTO; |
509 | else |
510 | source = AUDIO_CNTRL0_SOURCE_SELECT_AUTO; |
511 | break; |
512 | } |
513 | |
514 | /* |
515 | * Tegra30 and later use a slightly modified version of the register |
516 | * layout to accomodate for changes related to supporting HDA as the |
517 | * audio input source for HDMI. The source select field has moved to |
518 | * the SOR_AUDIO_CNTRL0 register, but the error tolerance and frames |
519 | * per block fields remain in the AUDIO_CNTRL0 register. |
520 | */ |
521 | if (hdmi->config->has_hda) { |
522 | /* |
523 | * Inject null samples into the audio FIFO for every frame in |
524 | * which the codec did not receive any samples. This applies |
525 | * to stereo LPCM only. |
526 | * |
527 | * XXX: This seems to be a remnant of MCP days when this was |
528 | * used to work around issues with monitors not being able to |
529 | * play back system startup sounds early. It is possibly not |
530 | * needed on Linux at all. |
531 | */ |
532 | if (hdmi->format.channels == 2) |
533 | value = SOR_AUDIO_CNTRL0_INJECT_NULLSMPL; |
534 | else |
535 | value = 0; |
536 | |
537 | value |= source; |
538 | |
539 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0); |
540 | } |
541 | |
542 | /* |
543 | * On Tegra20, HDA is not a supported audio source and the source |
544 | * select field is part of the AUDIO_CNTRL0 register. |
545 | */ |
546 | value = AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0) | |
547 | AUDIO_CNTRL0_ERROR_TOLERANCE(6); |
548 | |
549 | if (!hdmi->config->has_hda) |
550 | value |= source; |
551 | |
552 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0); |
553 | |
554 | /* |
555 | * Advertise support for High Bit-Rate on Tegra114 and later. |
556 | */ |
557 | if (hdmi->config->has_hbr) { |
558 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_AUDIO_SPARE0); |
559 | value |= SOR_AUDIO_SPARE0_HBR_ENABLE; |
560 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_SPARE0); |
561 | } |
562 | |
563 | err = tegra_hdmi_get_audio_config(audio_freq: hdmi->format.sample_rate, |
564 | pix_clock: hdmi->pixel_clock, config: &config); |
565 | if (err < 0) { |
566 | dev_err(hdmi->dev, |
567 | "cannot set audio to %u Hz at %u Hz pixel clock\n" , |
568 | hdmi->format.sample_rate, hdmi->pixel_clock); |
569 | return err; |
570 | } |
571 | |
572 | dev_dbg(hdmi->dev, "audio: pixclk=%u, n=%u, cts=%u, aval=%u\n" , |
573 | hdmi->pixel_clock, config.n, config.cts, config.aval); |
574 | |
575 | tegra_hdmi_writel(hdmi, value: 0, HDMI_NV_PDISP_HDMI_ACR_CTRL); |
576 | |
577 | value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE | |
578 | AUDIO_N_VALUE(config.n - 1); |
579 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N); |
580 | |
581 | tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config.n) | ACR_ENABLE, |
582 | HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH); |
583 | |
584 | tegra_hdmi_writel(hdmi, ACR_SUBPACK_CTS(config.cts), |
585 | HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW); |
586 | |
587 | value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1); |
588 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE); |
589 | |
590 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N); |
591 | value &= ~AUDIO_N_RESETF; |
592 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N); |
593 | |
594 | if (hdmi->config->has_hda) |
595 | tegra_hdmi_write_aval(hdmi, value: config.aval); |
596 | |
597 | tegra_hdmi_setup_audio_fs_tables(hdmi); |
598 | |
599 | return 0; |
600 | } |
601 | |
602 | static void tegra_hdmi_disable_audio(struct tegra_hdmi *hdmi) |
603 | { |
604 | u32 value; |
605 | |
606 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); |
607 | value &= ~GENERIC_CTRL_AUDIO; |
608 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); |
609 | } |
610 | |
611 | static void tegra_hdmi_enable_audio(struct tegra_hdmi *hdmi) |
612 | { |
613 | u32 value; |
614 | |
615 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); |
616 | value |= GENERIC_CTRL_AUDIO; |
617 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); |
618 | } |
619 | |
620 | static void tegra_hdmi_write_eld(struct tegra_hdmi *hdmi) |
621 | { |
622 | size_t length = drm_eld_size(eld: hdmi->output.connector.eld), i; |
623 | u32 value; |
624 | |
625 | for (i = 0; i < length; i++) |
626 | tegra_hdmi_writel(hdmi, value: i << 8 | hdmi->output.connector.eld[i], |
627 | HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR); |
628 | |
629 | /* |
630 | * The HDA codec will always report an ELD buffer size of 96 bytes and |
631 | * the HDA codec driver will check that each byte read from the buffer |
632 | * is valid. Therefore every byte must be written, even if no 96 bytes |
633 | * were parsed from EDID. |
634 | */ |
635 | for (i = length; i < HDMI_ELD_BUFFER_SIZE; i++) |
636 | tegra_hdmi_writel(hdmi, value: i << 8 | 0, |
637 | HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR); |
638 | |
639 | value = SOR_AUDIO_HDA_PRESENSE_VALID | SOR_AUDIO_HDA_PRESENSE_PRESENT; |
640 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE); |
641 | } |
642 | |
643 | static inline u32 tegra_hdmi_subpack(const u8 *ptr, size_t size) |
644 | { |
645 | u32 value = 0; |
646 | size_t i; |
647 | |
648 | for (i = size; i > 0; i--) |
649 | value = (value << 8) | ptr[i - 1]; |
650 | |
651 | return value; |
652 | } |
653 | |
654 | static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data, |
655 | size_t size) |
656 | { |
657 | const u8 *ptr = data; |
658 | unsigned long offset; |
659 | size_t i, j; |
660 | u32 value; |
661 | |
662 | switch (ptr[0]) { |
663 | case HDMI_INFOFRAME_TYPE_AVI: |
664 | offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER; |
665 | break; |
666 | |
667 | case HDMI_INFOFRAME_TYPE_AUDIO: |
668 | offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER; |
669 | break; |
670 | |
671 | case HDMI_INFOFRAME_TYPE_VENDOR: |
672 | offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER; |
673 | break; |
674 | |
675 | default: |
676 | dev_err(hdmi->dev, "unsupported infoframe type: %02x\n" , |
677 | ptr[0]); |
678 | return; |
679 | } |
680 | |
681 | value = INFOFRAME_HEADER_TYPE(ptr[0]) | |
682 | INFOFRAME_HEADER_VERSION(ptr[1]) | |
683 | INFOFRAME_HEADER_LEN(ptr[2]); |
684 | tegra_hdmi_writel(hdmi, value, offset); |
685 | offset++; |
686 | |
687 | /* |
688 | * Each subpack contains 7 bytes, divided into: |
689 | * - subpack_low: bytes 0 - 3 |
690 | * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00) |
691 | */ |
692 | for (i = 3, j = 0; i < size; i += 7, j += 8) { |
693 | size_t rem = size - i, num = min_t(size_t, rem, 4); |
694 | |
695 | value = tegra_hdmi_subpack(ptr: &ptr[i], size: num); |
696 | tegra_hdmi_writel(hdmi, value, offset: offset++); |
697 | |
698 | num = min_t(size_t, rem - num, 3); |
699 | |
700 | value = tegra_hdmi_subpack(ptr: &ptr[i + 4], size: num); |
701 | tegra_hdmi_writel(hdmi, value, offset: offset++); |
702 | } |
703 | } |
704 | |
705 | static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, |
706 | struct drm_display_mode *mode) |
707 | { |
708 | struct hdmi_avi_infoframe frame; |
709 | u8 buffer[17]; |
710 | ssize_t err; |
711 | |
712 | err = drm_hdmi_avi_infoframe_from_display_mode(frame: &frame, |
713 | connector: &hdmi->output.connector, mode); |
714 | if (err < 0) { |
715 | dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n" , err); |
716 | return; |
717 | } |
718 | |
719 | err = hdmi_avi_infoframe_pack(frame: &frame, buffer, size: sizeof(buffer)); |
720 | if (err < 0) { |
721 | dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n" , err); |
722 | return; |
723 | } |
724 | |
725 | tegra_hdmi_write_infopack(hdmi, data: buffer, size: err); |
726 | } |
727 | |
728 | static void tegra_hdmi_disable_avi_infoframe(struct tegra_hdmi *hdmi) |
729 | { |
730 | u32 value; |
731 | |
732 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); |
733 | value &= ~INFOFRAME_CTRL_ENABLE; |
734 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); |
735 | } |
736 | |
737 | static void tegra_hdmi_enable_avi_infoframe(struct tegra_hdmi *hdmi) |
738 | { |
739 | u32 value; |
740 | |
741 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); |
742 | value |= INFOFRAME_CTRL_ENABLE; |
743 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); |
744 | } |
745 | |
746 | static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) |
747 | { |
748 | struct hdmi_audio_infoframe frame; |
749 | u8 buffer[14]; |
750 | ssize_t err; |
751 | |
752 | err = hdmi_audio_infoframe_init(frame: &frame); |
753 | if (err < 0) { |
754 | dev_err(hdmi->dev, "failed to setup audio infoframe: %zd\n" , |
755 | err); |
756 | return; |
757 | } |
758 | |
759 | frame.channels = hdmi->format.channels; |
760 | |
761 | err = hdmi_audio_infoframe_pack(frame: &frame, buffer, size: sizeof(buffer)); |
762 | if (err < 0) { |
763 | dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n" , |
764 | err); |
765 | return; |
766 | } |
767 | |
768 | /* |
769 | * The audio infoframe has only one set of subpack registers, so the |
770 | * infoframe needs to be truncated. One set of subpack registers can |
771 | * contain 7 bytes. Including the 3 byte header only the first 10 |
772 | * bytes can be programmed. |
773 | */ |
774 | tegra_hdmi_write_infopack(hdmi, data: buffer, min_t(size_t, 10, err)); |
775 | } |
776 | |
777 | static void tegra_hdmi_disable_audio_infoframe(struct tegra_hdmi *hdmi) |
778 | { |
779 | u32 value; |
780 | |
781 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); |
782 | value &= ~INFOFRAME_CTRL_ENABLE; |
783 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); |
784 | } |
785 | |
786 | static void tegra_hdmi_enable_audio_infoframe(struct tegra_hdmi *hdmi) |
787 | { |
788 | u32 value; |
789 | |
790 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); |
791 | value |= INFOFRAME_CTRL_ENABLE; |
792 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); |
793 | } |
794 | |
795 | static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi) |
796 | { |
797 | struct hdmi_vendor_infoframe frame; |
798 | u8 buffer[10]; |
799 | ssize_t err; |
800 | |
801 | hdmi_vendor_infoframe_init(frame: &frame); |
802 | frame.s3d_struct = HDMI_3D_STRUCTURE_FRAME_PACKING; |
803 | |
804 | err = hdmi_vendor_infoframe_pack(frame: &frame, buffer, size: sizeof(buffer)); |
805 | if (err < 0) { |
806 | dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n" , |
807 | err); |
808 | return; |
809 | } |
810 | |
811 | tegra_hdmi_write_infopack(hdmi, data: buffer, size: err); |
812 | } |
813 | |
814 | static void tegra_hdmi_disable_stereo_infoframe(struct tegra_hdmi *hdmi) |
815 | { |
816 | u32 value; |
817 | |
818 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); |
819 | value &= ~GENERIC_CTRL_ENABLE; |
820 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); |
821 | } |
822 | |
823 | static void tegra_hdmi_enable_stereo_infoframe(struct tegra_hdmi *hdmi) |
824 | { |
825 | u32 value; |
826 | |
827 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); |
828 | value |= GENERIC_CTRL_ENABLE; |
829 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); |
830 | } |
831 | |
832 | static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi, |
833 | const struct tmds_config *tmds) |
834 | { |
835 | u32 value; |
836 | |
837 | tegra_hdmi_writel(hdmi, value: tmds->pll0, HDMI_NV_PDISP_SOR_PLL0); |
838 | tegra_hdmi_writel(hdmi, value: tmds->pll1, HDMI_NV_PDISP_SOR_PLL1); |
839 | tegra_hdmi_writel(hdmi, value: tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT); |
840 | |
841 | tegra_hdmi_writel(hdmi, value: tmds->drive_current, |
842 | HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT); |
843 | |
844 | value = tegra_hdmi_readl(hdmi, offset: hdmi->config->fuse_override_offset); |
845 | value |= hdmi->config->fuse_override_value; |
846 | tegra_hdmi_writel(hdmi, value, offset: hdmi->config->fuse_override_offset); |
847 | |
848 | if (hdmi->config->has_sor_io_peak_current) |
849 | tegra_hdmi_writel(hdmi, value: tmds->peak_current, |
850 | HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT); |
851 | } |
852 | |
853 | static int tegra_hdmi_reconfigure_audio(struct tegra_hdmi *hdmi) |
854 | { |
855 | int err; |
856 | |
857 | err = tegra_hdmi_setup_audio(hdmi); |
858 | if (err < 0) { |
859 | tegra_hdmi_disable_audio_infoframe(hdmi); |
860 | tegra_hdmi_disable_audio(hdmi); |
861 | } else { |
862 | tegra_hdmi_setup_audio_infoframe(hdmi); |
863 | tegra_hdmi_enable_audio_infoframe(hdmi); |
864 | tegra_hdmi_enable_audio(hdmi); |
865 | } |
866 | |
867 | return err; |
868 | } |
869 | |
870 | static bool tegra_output_is_hdmi(struct tegra_output *output) |
871 | { |
872 | return output->connector.display_info.is_hdmi; |
873 | } |
874 | |
875 | static enum drm_connector_status |
876 | tegra_hdmi_connector_detect(struct drm_connector *connector, bool force) |
877 | { |
878 | struct tegra_output *output = connector_to_output(c: connector); |
879 | struct tegra_hdmi *hdmi = to_hdmi(output); |
880 | enum drm_connector_status status; |
881 | |
882 | status = tegra_output_connector_detect(connector, force); |
883 | if (status == connector_status_connected) |
884 | return status; |
885 | |
886 | tegra_hdmi_writel(hdmi, value: 0, HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE); |
887 | return status; |
888 | } |
889 | |
890 | #define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name } |
891 | |
892 | static const struct debugfs_reg32 tegra_hdmi_regs[] = { |
893 | DEBUGFS_REG32(HDMI_CTXSW), |
894 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_STATE0), |
895 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_STATE1), |
896 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_STATE2), |
897 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_AN_MSB), |
898 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_AN_LSB), |
899 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_CN_MSB), |
900 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_CN_LSB), |
901 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB), |
902 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB), |
903 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB), |
904 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB), |
905 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB), |
906 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB), |
907 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB), |
908 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB), |
909 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_CTRL), |
910 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_CMODE), |
911 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB), |
912 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB), |
913 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB), |
914 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2), |
915 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1), |
916 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_RI), |
917 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_CS_MSB), |
918 | DEBUGFS_REG32(HDMI_NV_PDISP_RG_HDCP_CS_LSB), |
919 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_EMU0), |
920 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0), |
921 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_EMU1), |
922 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_EMU2), |
923 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL), |
924 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS), |
925 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER), |
926 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW), |
927 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH), |
928 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL), |
929 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS), |
930 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER), |
931 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW), |
932 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH), |
933 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW), |
934 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH), |
935 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_CTRL), |
936 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_STATUS), |
937 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_HEADER), |
938 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW), |
939 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH), |
940 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW), |
941 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH), |
942 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW), |
943 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH), |
944 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW), |
945 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH), |
946 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_CTRL), |
947 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW), |
948 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH), |
949 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW), |
950 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH), |
951 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW), |
952 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH), |
953 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW), |
954 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH), |
955 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW), |
956 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH), |
957 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW), |
958 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH), |
959 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW), |
960 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH), |
961 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_CTRL), |
962 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT), |
963 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW), |
964 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GCP_CTRL), |
965 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GCP_STATUS), |
966 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_GCP_SUBPACK), |
967 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1), |
968 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2), |
969 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_EMU0), |
970 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_EMU1), |
971 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_EMU1_RDATA), |
972 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_SPARE), |
973 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1), |
974 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2), |
975 | DEBUGFS_REG32(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL), |
976 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_CAP), |
977 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_PWR), |
978 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_TEST), |
979 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_PLL0), |
980 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_PLL1), |
981 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_PLL2), |
982 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_CSTM), |
983 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_LVDS), |
984 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_CRCA), |
985 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_CRCB), |
986 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_BLANK), |
987 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_CTL), |
988 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(0)), |
989 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(1)), |
990 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(2)), |
991 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(3)), |
992 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(4)), |
993 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(5)), |
994 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(6)), |
995 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(7)), |
996 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(8)), |
997 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(9)), |
998 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(10)), |
999 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(11)), |
1000 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(12)), |
1001 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(13)), |
1002 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(14)), |
1003 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_SEQ_INST(15)), |
1004 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_VCRCA0), |
1005 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_VCRCA1), |
1006 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_CCRCA0), |
1007 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_CCRCA1), |
1008 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_EDATAA0), |
1009 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_EDATAA1), |
1010 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_COUNTA0), |
1011 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_COUNTA1), |
1012 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_DEBUGA0), |
1013 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_DEBUGA1), |
1014 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_TRIG), |
1015 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_MSCHECK), |
1016 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT), |
1017 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_DEBUG0), |
1018 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_DEBUG1), |
1019 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_DEBUG2), |
1020 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_FS(0)), |
1021 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_FS(1)), |
1022 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_FS(2)), |
1023 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_FS(3)), |
1024 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_FS(4)), |
1025 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_FS(5)), |
1026 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_FS(6)), |
1027 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH), |
1028 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_THRESHOLD), |
1029 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_CNTRL0), |
1030 | DEBUGFS_REG32(HDMI_NV_PDISP_AUDIO_N), |
1031 | DEBUGFS_REG32(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING), |
1032 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_REFCLK), |
1033 | DEBUGFS_REG32(HDMI_NV_PDISP_CRC_CONTROL), |
1034 | DEBUGFS_REG32(HDMI_NV_PDISP_INPUT_CONTROL), |
1035 | DEBUGFS_REG32(HDMI_NV_PDISP_SCRATCH), |
1036 | DEBUGFS_REG32(HDMI_NV_PDISP_PE_CURRENT), |
1037 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_CTRL), |
1038 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_DEBUG0), |
1039 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_DEBUG1), |
1040 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_DEBUG2), |
1041 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_HDCP_KEY_0), |
1042 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_HDCP_KEY_1), |
1043 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_HDCP_KEY_2), |
1044 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_HDCP_KEY_3), |
1045 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG), |
1046 | DEBUGFS_REG32(HDMI_NV_PDISP_KEY_SKEY_INDEX), |
1047 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0), |
1048 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_AUDIO_SPARE0), |
1049 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH0), |
1050 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH1), |
1051 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR), |
1052 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE), |
1053 | DEBUGFS_REG32(HDMI_NV_PDISP_INT_STATUS), |
1054 | DEBUGFS_REG32(HDMI_NV_PDISP_INT_MASK), |
1055 | DEBUGFS_REG32(HDMI_NV_PDISP_INT_ENABLE), |
1056 | DEBUGFS_REG32(HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT), |
1057 | }; |
1058 | |
1059 | static int tegra_hdmi_show_regs(struct seq_file *s, void *data) |
1060 | { |
1061 | struct drm_info_node *node = s->private; |
1062 | struct tegra_hdmi *hdmi = node->info_ent->data; |
1063 | struct drm_crtc *crtc = hdmi->output.encoder.crtc; |
1064 | struct drm_device *drm = node->minor->dev; |
1065 | unsigned int i; |
1066 | int err = 0; |
1067 | |
1068 | drm_modeset_lock_all(dev: drm); |
1069 | |
1070 | if (!crtc || !crtc->state->active) { |
1071 | err = -EBUSY; |
1072 | goto unlock; |
1073 | } |
1074 | |
1075 | for (i = 0; i < ARRAY_SIZE(tegra_hdmi_regs); i++) { |
1076 | unsigned int offset = tegra_hdmi_regs[i].offset; |
1077 | |
1078 | seq_printf(m: s, fmt: "%-56s %#05x %08x\n" , tegra_hdmi_regs[i].name, |
1079 | offset, tegra_hdmi_readl(hdmi, offset)); |
1080 | } |
1081 | |
1082 | unlock: |
1083 | drm_modeset_unlock_all(dev: drm); |
1084 | return err; |
1085 | } |
1086 | |
1087 | static struct drm_info_list debugfs_files[] = { |
1088 | { "regs" , tegra_hdmi_show_regs, 0, NULL }, |
1089 | }; |
1090 | |
1091 | static int tegra_hdmi_late_register(struct drm_connector *connector) |
1092 | { |
1093 | struct tegra_output *output = connector_to_output(c: connector); |
1094 | unsigned int i, count = ARRAY_SIZE(debugfs_files); |
1095 | struct drm_minor *minor = connector->dev->primary; |
1096 | struct dentry *root = connector->debugfs_entry; |
1097 | struct tegra_hdmi *hdmi = to_hdmi(output); |
1098 | |
1099 | hdmi->debugfs_files = kmemdup(p: debugfs_files, size: sizeof(debugfs_files), |
1100 | GFP_KERNEL); |
1101 | if (!hdmi->debugfs_files) |
1102 | return -ENOMEM; |
1103 | |
1104 | for (i = 0; i < count; i++) |
1105 | hdmi->debugfs_files[i].data = hdmi; |
1106 | |
1107 | drm_debugfs_create_files(files: hdmi->debugfs_files, count, root, minor); |
1108 | |
1109 | return 0; |
1110 | } |
1111 | |
1112 | static void tegra_hdmi_early_unregister(struct drm_connector *connector) |
1113 | { |
1114 | struct tegra_output *output = connector_to_output(c: connector); |
1115 | struct drm_minor *minor = connector->dev->primary; |
1116 | unsigned int count = ARRAY_SIZE(debugfs_files); |
1117 | struct tegra_hdmi *hdmi = to_hdmi(output); |
1118 | |
1119 | drm_debugfs_remove_files(files: hdmi->debugfs_files, count, |
1120 | root: connector->debugfs_entry, minor); |
1121 | kfree(objp: hdmi->debugfs_files); |
1122 | hdmi->debugfs_files = NULL; |
1123 | } |
1124 | |
1125 | static const struct drm_connector_funcs tegra_hdmi_connector_funcs = { |
1126 | .reset = drm_atomic_helper_connector_reset, |
1127 | .detect = tegra_hdmi_connector_detect, |
1128 | .fill_modes = drm_helper_probe_single_connector_modes, |
1129 | .destroy = tegra_output_connector_destroy, |
1130 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
1131 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
1132 | .late_register = tegra_hdmi_late_register, |
1133 | .early_unregister = tegra_hdmi_early_unregister, |
1134 | }; |
1135 | |
1136 | static enum drm_mode_status |
1137 | tegra_hdmi_connector_mode_valid(struct drm_connector *connector, |
1138 | struct drm_display_mode *mode) |
1139 | { |
1140 | struct tegra_output *output = connector_to_output(c: connector); |
1141 | struct tegra_hdmi *hdmi = to_hdmi(output); |
1142 | unsigned long pclk = mode->clock * 1000; |
1143 | enum drm_mode_status status = MODE_OK; |
1144 | struct clk *parent; |
1145 | long err; |
1146 | |
1147 | parent = clk_get_parent(clk: hdmi->clk_parent); |
1148 | |
1149 | err = clk_round_rate(clk: parent, rate: pclk * 4); |
1150 | if (err <= 0) |
1151 | status = MODE_NOCLOCK; |
1152 | |
1153 | return status; |
1154 | } |
1155 | |
1156 | static const struct drm_connector_helper_funcs |
1157 | tegra_hdmi_connector_helper_funcs = { |
1158 | .get_modes = tegra_output_connector_get_modes, |
1159 | .mode_valid = tegra_hdmi_connector_mode_valid, |
1160 | }; |
1161 | |
1162 | static void tegra_hdmi_encoder_disable(struct drm_encoder *encoder) |
1163 | { |
1164 | struct tegra_output *output = encoder_to_output(e: encoder); |
1165 | struct tegra_dc *dc = to_tegra_dc(crtc: encoder->crtc); |
1166 | struct tegra_hdmi *hdmi = to_hdmi(output); |
1167 | u32 value; |
1168 | int err; |
1169 | |
1170 | tegra_hdmi_audio_lock(hdmi); |
1171 | |
1172 | /* |
1173 | * The following accesses registers of the display controller, so make |
1174 | * sure it's only executed when the output is attached to one. |
1175 | */ |
1176 | if (dc) { |
1177 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); |
1178 | value &= ~HDMI_ENABLE; |
1179 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); |
1180 | |
1181 | tegra_dc_commit(dc); |
1182 | } |
1183 | |
1184 | if (!hdmi->dvi) { |
1185 | if (hdmi->stereo) |
1186 | tegra_hdmi_disable_stereo_infoframe(hdmi); |
1187 | |
1188 | tegra_hdmi_disable_audio_infoframe(hdmi); |
1189 | tegra_hdmi_disable_avi_infoframe(hdmi); |
1190 | tegra_hdmi_disable_audio(hdmi); |
1191 | } |
1192 | |
1193 | tegra_hdmi_writel(hdmi, value: 0, HDMI_NV_PDISP_INT_ENABLE); |
1194 | tegra_hdmi_writel(hdmi, value: 0, HDMI_NV_PDISP_INT_MASK); |
1195 | |
1196 | hdmi->pixel_clock = 0; |
1197 | |
1198 | tegra_hdmi_audio_unlock(hdmi); |
1199 | |
1200 | err = host1x_client_suspend(client: &hdmi->client); |
1201 | if (err < 0) |
1202 | dev_err(hdmi->dev, "failed to suspend: %d\n" , err); |
1203 | } |
1204 | |
1205 | static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder) |
1206 | { |
1207 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; |
1208 | unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey; |
1209 | struct tegra_output *output = encoder_to_output(e: encoder); |
1210 | struct tegra_dc *dc = to_tegra_dc(crtc: encoder->crtc); |
1211 | struct tegra_hdmi *hdmi = to_hdmi(output); |
1212 | unsigned int pulse_start, div82; |
1213 | int retries = 1000; |
1214 | u32 value; |
1215 | int err; |
1216 | |
1217 | err = host1x_client_resume(client: &hdmi->client); |
1218 | if (err < 0) { |
1219 | dev_err(hdmi->dev, "failed to resume: %d\n" , err); |
1220 | return; |
1221 | } |
1222 | |
1223 | tegra_hdmi_audio_lock(hdmi); |
1224 | |
1225 | /* |
1226 | * Enable and unmask the HDA codec SCRATCH0 register interrupt. This |
1227 | * is used for interoperability between the HDA codec driver and the |
1228 | * HDMI driver. |
1229 | */ |
1230 | tegra_hdmi_writel(hdmi, INT_CODEC_SCRATCH0, HDMI_NV_PDISP_INT_ENABLE); |
1231 | tegra_hdmi_writel(hdmi, INT_CODEC_SCRATCH0, HDMI_NV_PDISP_INT_MASK); |
1232 | |
1233 | hdmi->pixel_clock = mode->clock * 1000; |
1234 | h_sync_width = mode->hsync_end - mode->hsync_start; |
1235 | h_back_porch = mode->htotal - mode->hsync_end; |
1236 | h_front_porch = mode->hsync_start - mode->hdisplay; |
1237 | |
1238 | err = dev_pm_opp_set_rate(dev: hdmi->dev, target_freq: hdmi->pixel_clock); |
1239 | if (err < 0) { |
1240 | dev_err(hdmi->dev, "failed to set HDMI clock frequency: %d\n" , |
1241 | err); |
1242 | } |
1243 | |
1244 | DRM_DEBUG_KMS("HDMI clock rate: %lu Hz\n" , clk_get_rate(hdmi->clk)); |
1245 | |
1246 | /* power up sequence */ |
1247 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PLL0); |
1248 | value &= ~SOR_PLL_PDBG; |
1249 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_PLL0); |
1250 | |
1251 | usleep_range(min: 10, max: 20); |
1252 | |
1253 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PLL0); |
1254 | value &= ~SOR_PLL_PWR; |
1255 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_PLL0); |
1256 | |
1257 | tegra_dc_writel(dc, VSYNC_H_POSITION(1), |
1258 | DC_DISP_DISP_TIMING_OPTIONS); |
1259 | tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE_888, |
1260 | DC_DISP_DISP_COLOR_CONTROL); |
1261 | |
1262 | /* video_preamble uses h_pulse2 */ |
1263 | pulse_start = 1 + h_sync_width + h_back_porch - 10; |
1264 | |
1265 | tegra_dc_writel(dc, H_PULSE2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0); |
1266 | |
1267 | value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE | |
1268 | PULSE_LAST_END_A; |
1269 | tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL); |
1270 | |
1271 | value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8); |
1272 | tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A); |
1273 | |
1274 | value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) | |
1275 | VSYNC_WINDOW_ENABLE; |
1276 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW); |
1277 | |
1278 | if (dc->pipe) |
1279 | value = HDMI_SRC_DISPLAYB; |
1280 | else |
1281 | value = HDMI_SRC_DISPLAYA; |
1282 | |
1283 | if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) || |
1284 | (mode->vdisplay == 576))) |
1285 | tegra_hdmi_writel(hdmi, |
1286 | value: value | ARM_VIDEO_RANGE_FULL, |
1287 | HDMI_NV_PDISP_INPUT_CONTROL); |
1288 | else |
1289 | tegra_hdmi_writel(hdmi, |
1290 | value: value | ARM_VIDEO_RANGE_LIMITED, |
1291 | HDMI_NV_PDISP_INPUT_CONTROL); |
1292 | |
1293 | div82 = clk_get_rate(clk: hdmi->clk) / 1000000 * 4; |
1294 | value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82); |
1295 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK); |
1296 | |
1297 | hdmi->dvi = !tegra_output_is_hdmi(output); |
1298 | if (!hdmi->dvi) { |
1299 | /* |
1300 | * Make sure that the audio format has been configured before |
1301 | * enabling audio, otherwise we may try to divide by zero. |
1302 | */ |
1303 | if (hdmi->format.sample_rate > 0) { |
1304 | err = tegra_hdmi_setup_audio(hdmi); |
1305 | if (err < 0) |
1306 | hdmi->dvi = true; |
1307 | } |
1308 | } |
1309 | |
1310 | if (hdmi->config->has_hda) |
1311 | tegra_hdmi_write_eld(hdmi); |
1312 | |
1313 | rekey = HDMI_REKEY_DEFAULT; |
1314 | value = HDMI_CTRL_REKEY(rekey); |
1315 | value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch + |
1316 | h_front_porch - rekey - 18) / 32); |
1317 | |
1318 | if (!hdmi->dvi) |
1319 | value |= HDMI_CTRL_ENABLE; |
1320 | |
1321 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL); |
1322 | |
1323 | if (!hdmi->dvi) { |
1324 | tegra_hdmi_setup_avi_infoframe(hdmi, mode); |
1325 | tegra_hdmi_setup_audio_infoframe(hdmi); |
1326 | |
1327 | if (hdmi->stereo) |
1328 | tegra_hdmi_setup_stereo_infoframe(hdmi); |
1329 | } |
1330 | |
1331 | /* TMDS CONFIG */ |
1332 | for (i = 0; i < hdmi->config->num_tmds; i++) { |
1333 | if (hdmi->pixel_clock <= hdmi->config->tmds[i].pclk) { |
1334 | tegra_hdmi_setup_tmds(hdmi, tmds: &hdmi->config->tmds[i]); |
1335 | break; |
1336 | } |
1337 | } |
1338 | |
1339 | tegra_hdmi_writel(hdmi, |
1340 | SOR_SEQ_PU_PC(0) | |
1341 | SOR_SEQ_PU_PC_ALT(0) | |
1342 | SOR_SEQ_PD_PC(8) | |
1343 | SOR_SEQ_PD_PC_ALT(8), |
1344 | HDMI_NV_PDISP_SOR_SEQ_CTL); |
1345 | |
1346 | value = SOR_SEQ_INST_WAIT_TIME(1) | |
1347 | SOR_SEQ_INST_WAIT_UNITS_VSYNC | |
1348 | SOR_SEQ_INST_HALT | |
1349 | SOR_SEQ_INST_PIN_A_LOW | |
1350 | SOR_SEQ_INST_PIN_B_LOW | |
1351 | SOR_SEQ_INST_DRIVE_PWM_OUT_LO; |
1352 | |
1353 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0)); |
1354 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8)); |
1355 | |
1356 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_CSTM); |
1357 | value &= ~SOR_CSTM_ROTCLK(~0); |
1358 | value |= SOR_CSTM_ROTCLK(2); |
1359 | value |= SOR_CSTM_PLLDIV; |
1360 | value &= ~SOR_CSTM_LVDS_ENABLE; |
1361 | value &= ~SOR_CSTM_MODE_MASK; |
1362 | value |= SOR_CSTM_MODE_TMDS; |
1363 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM); |
1364 | |
1365 | /* start SOR */ |
1366 | tegra_hdmi_writel(hdmi, |
1367 | SOR_PWR_NORMAL_STATE_PU | |
1368 | SOR_PWR_NORMAL_START_NORMAL | |
1369 | SOR_PWR_SAFE_STATE_PD | |
1370 | SOR_PWR_SETTING_NEW_TRIGGER, |
1371 | HDMI_NV_PDISP_SOR_PWR); |
1372 | tegra_hdmi_writel(hdmi, |
1373 | SOR_PWR_NORMAL_STATE_PU | |
1374 | SOR_PWR_NORMAL_START_NORMAL | |
1375 | SOR_PWR_SAFE_STATE_PD | |
1376 | SOR_PWR_SETTING_NEW_DONE, |
1377 | HDMI_NV_PDISP_SOR_PWR); |
1378 | |
1379 | do { |
1380 | BUG_ON(--retries < 0); |
1381 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR); |
1382 | } while (value & SOR_PWR_SETTING_NEW_PENDING); |
1383 | |
1384 | value = SOR_STATE_ASY_CRCMODE_COMPLETE | |
1385 | SOR_STATE_ASY_OWNER_HEAD0 | |
1386 | SOR_STATE_ASY_SUBOWNER_BOTH | |
1387 | SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A | |
1388 | SOR_STATE_ASY_DEPOL_POS; |
1389 | |
1390 | /* setup sync polarities */ |
1391 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) |
1392 | value |= SOR_STATE_ASY_HSYNCPOL_POS; |
1393 | |
1394 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) |
1395 | value |= SOR_STATE_ASY_HSYNCPOL_NEG; |
1396 | |
1397 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) |
1398 | value |= SOR_STATE_ASY_VSYNCPOL_POS; |
1399 | |
1400 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) |
1401 | value |= SOR_STATE_ASY_VSYNCPOL_NEG; |
1402 | |
1403 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2); |
1404 | |
1405 | value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL; |
1406 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1); |
1407 | |
1408 | tegra_hdmi_writel(hdmi, value: 0, HDMI_NV_PDISP_SOR_STATE0); |
1409 | tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0); |
1410 | tegra_hdmi_writel(hdmi, value: value | SOR_STATE_ATTACHED, |
1411 | HDMI_NV_PDISP_SOR_STATE1); |
1412 | tegra_hdmi_writel(hdmi, value: 0, HDMI_NV_PDISP_SOR_STATE0); |
1413 | |
1414 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); |
1415 | value |= HDMI_ENABLE; |
1416 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); |
1417 | |
1418 | tegra_dc_commit(dc); |
1419 | |
1420 | if (!hdmi->dvi) { |
1421 | tegra_hdmi_enable_avi_infoframe(hdmi); |
1422 | tegra_hdmi_enable_audio_infoframe(hdmi); |
1423 | tegra_hdmi_enable_audio(hdmi); |
1424 | |
1425 | if (hdmi->stereo) |
1426 | tegra_hdmi_enable_stereo_infoframe(hdmi); |
1427 | } |
1428 | |
1429 | /* TODO: add HDCP support */ |
1430 | |
1431 | tegra_hdmi_audio_unlock(hdmi); |
1432 | } |
1433 | |
1434 | static int |
1435 | tegra_hdmi_encoder_atomic_check(struct drm_encoder *encoder, |
1436 | struct drm_crtc_state *crtc_state, |
1437 | struct drm_connector_state *conn_state) |
1438 | { |
1439 | struct tegra_output *output = encoder_to_output(e: encoder); |
1440 | struct tegra_dc *dc = to_tegra_dc(crtc: conn_state->crtc); |
1441 | unsigned long pclk = crtc_state->mode.clock * 1000; |
1442 | struct tegra_hdmi *hdmi = to_hdmi(output); |
1443 | int err; |
1444 | |
1445 | err = tegra_dc_state_setup_clock(dc, crtc_state, clk: hdmi->clk_parent, |
1446 | pclk, div: 0); |
1447 | if (err < 0) { |
1448 | dev_err(output->dev, "failed to setup CRTC state: %d\n" , err); |
1449 | return err; |
1450 | } |
1451 | |
1452 | return err; |
1453 | } |
1454 | |
1455 | static const struct drm_encoder_helper_funcs tegra_hdmi_encoder_helper_funcs = { |
1456 | .disable = tegra_hdmi_encoder_disable, |
1457 | .enable = tegra_hdmi_encoder_enable, |
1458 | .atomic_check = tegra_hdmi_encoder_atomic_check, |
1459 | }; |
1460 | |
1461 | static int tegra_hdmi_hw_params(struct device *dev, void *data, |
1462 | struct hdmi_codec_daifmt *fmt, |
1463 | struct hdmi_codec_params *hparms) |
1464 | { |
1465 | struct tegra_hdmi *hdmi = data; |
1466 | int ret = 0; |
1467 | |
1468 | tegra_hdmi_audio_lock(hdmi); |
1469 | |
1470 | hdmi->format.sample_rate = hparms->sample_rate; |
1471 | hdmi->format.channels = hparms->channels; |
1472 | |
1473 | if (hdmi->pixel_clock && !hdmi->dvi) |
1474 | ret = tegra_hdmi_reconfigure_audio(hdmi); |
1475 | |
1476 | tegra_hdmi_audio_unlock(hdmi); |
1477 | |
1478 | return ret; |
1479 | } |
1480 | |
1481 | static int tegra_hdmi_audio_startup(struct device *dev, void *data) |
1482 | { |
1483 | struct tegra_hdmi *hdmi = data; |
1484 | int ret; |
1485 | |
1486 | ret = host1x_client_resume(client: &hdmi->client); |
1487 | if (ret < 0) |
1488 | dev_err(hdmi->dev, "failed to resume: %d\n" , ret); |
1489 | |
1490 | return ret; |
1491 | } |
1492 | |
1493 | static void tegra_hdmi_audio_shutdown(struct device *dev, void *data) |
1494 | { |
1495 | struct tegra_hdmi *hdmi = data; |
1496 | int ret; |
1497 | |
1498 | tegra_hdmi_audio_lock(hdmi); |
1499 | |
1500 | hdmi->format.sample_rate = 0; |
1501 | hdmi->format.channels = 0; |
1502 | |
1503 | tegra_hdmi_audio_unlock(hdmi); |
1504 | |
1505 | ret = host1x_client_suspend(client: &hdmi->client); |
1506 | if (ret < 0) |
1507 | dev_err(hdmi->dev, "failed to suspend: %d\n" , ret); |
1508 | } |
1509 | |
1510 | static const struct hdmi_codec_ops tegra_hdmi_codec_ops = { |
1511 | .hw_params = tegra_hdmi_hw_params, |
1512 | .audio_startup = tegra_hdmi_audio_startup, |
1513 | .audio_shutdown = tegra_hdmi_audio_shutdown, |
1514 | }; |
1515 | |
1516 | static int tegra_hdmi_codec_register(struct tegra_hdmi *hdmi) |
1517 | { |
1518 | struct hdmi_codec_pdata codec_data = {}; |
1519 | |
1520 | if (hdmi->config->has_hda) |
1521 | return 0; |
1522 | |
1523 | codec_data.ops = &tegra_hdmi_codec_ops; |
1524 | codec_data.data = hdmi; |
1525 | codec_data.spdif = 1; |
1526 | |
1527 | hdmi->audio_pdev = platform_device_register_data(parent: hdmi->dev, |
1528 | HDMI_CODEC_DRV_NAME, |
1529 | PLATFORM_DEVID_AUTO, |
1530 | data: &codec_data, |
1531 | size: sizeof(codec_data)); |
1532 | if (IS_ERR(ptr: hdmi->audio_pdev)) |
1533 | return PTR_ERR(ptr: hdmi->audio_pdev); |
1534 | |
1535 | hdmi->format.channels = 2; |
1536 | |
1537 | return 0; |
1538 | } |
1539 | |
1540 | static void tegra_hdmi_codec_unregister(struct tegra_hdmi *hdmi) |
1541 | { |
1542 | if (hdmi->audio_pdev) |
1543 | platform_device_unregister(hdmi->audio_pdev); |
1544 | } |
1545 | |
1546 | static int tegra_hdmi_init(struct host1x_client *client) |
1547 | { |
1548 | struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client); |
1549 | struct drm_device *drm = dev_get_drvdata(dev: client->host); |
1550 | struct drm_connector *connector; |
1551 | int err; |
1552 | |
1553 | hdmi->output.dev = client->dev; |
1554 | |
1555 | drm_simple_encoder_init(dev: drm, encoder: &hdmi->output.encoder, |
1556 | DRM_MODE_ENCODER_TMDS); |
1557 | drm_encoder_helper_add(encoder: &hdmi->output.encoder, |
1558 | funcs: &tegra_hdmi_encoder_helper_funcs); |
1559 | |
1560 | if (hdmi->output.bridge) { |
1561 | err = drm_bridge_attach(encoder: &hdmi->output.encoder, bridge: hdmi->output.bridge, |
1562 | NULL, flags: DRM_BRIDGE_ATTACH_NO_CONNECTOR); |
1563 | if (err) { |
1564 | dev_err(client->dev, "failed to attach bridge: %d\n" , |
1565 | err); |
1566 | return err; |
1567 | } |
1568 | |
1569 | connector = drm_bridge_connector_init(drm, encoder: &hdmi->output.encoder); |
1570 | if (IS_ERR(ptr: connector)) { |
1571 | dev_err(client->dev, |
1572 | "failed to initialize bridge connector: %pe\n" , |
1573 | connector); |
1574 | return PTR_ERR(ptr: connector); |
1575 | } |
1576 | |
1577 | drm_connector_attach_encoder(connector, encoder: &hdmi->output.encoder); |
1578 | } else { |
1579 | drm_connector_init_with_ddc(dev: drm, connector: &hdmi->output.connector, |
1580 | funcs: &tegra_hdmi_connector_funcs, |
1581 | DRM_MODE_CONNECTOR_HDMIA, |
1582 | ddc: hdmi->output.ddc); |
1583 | drm_connector_helper_add(connector: &hdmi->output.connector, |
1584 | funcs: &tegra_hdmi_connector_helper_funcs); |
1585 | hdmi->output.connector.dpms = DRM_MODE_DPMS_OFF; |
1586 | |
1587 | drm_connector_attach_encoder(connector: &hdmi->output.connector, |
1588 | encoder: &hdmi->output.encoder); |
1589 | drm_connector_register(connector: &hdmi->output.connector); |
1590 | } |
1591 | |
1592 | err = tegra_output_init(drm, output: &hdmi->output); |
1593 | if (err < 0) { |
1594 | dev_err(client->dev, "failed to initialize output: %d\n" , err); |
1595 | return err; |
1596 | } |
1597 | |
1598 | hdmi->output.encoder.possible_crtcs = 0x3; |
1599 | |
1600 | err = regulator_enable(regulator: hdmi->hdmi); |
1601 | if (err < 0) { |
1602 | dev_err(client->dev, "failed to enable HDMI regulator: %d\n" , |
1603 | err); |
1604 | goto output_exit; |
1605 | } |
1606 | |
1607 | err = regulator_enable(regulator: hdmi->pll); |
1608 | if (err < 0) { |
1609 | dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n" , err); |
1610 | goto disable_hdmi; |
1611 | } |
1612 | |
1613 | err = regulator_enable(regulator: hdmi->vdd); |
1614 | if (err < 0) { |
1615 | dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n" , err); |
1616 | goto disable_pll; |
1617 | } |
1618 | |
1619 | err = tegra_hdmi_codec_register(hdmi); |
1620 | if (err < 0) { |
1621 | dev_err(hdmi->dev, "failed to register audio codec: %d\n" , err); |
1622 | goto disable_vdd; |
1623 | } |
1624 | |
1625 | return 0; |
1626 | |
1627 | disable_vdd: |
1628 | regulator_disable(regulator: hdmi->vdd); |
1629 | disable_pll: |
1630 | regulator_disable(regulator: hdmi->pll); |
1631 | disable_hdmi: |
1632 | regulator_disable(regulator: hdmi->hdmi); |
1633 | output_exit: |
1634 | tegra_output_exit(output: &hdmi->output); |
1635 | |
1636 | return err; |
1637 | } |
1638 | |
1639 | static int tegra_hdmi_exit(struct host1x_client *client) |
1640 | { |
1641 | struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client); |
1642 | |
1643 | tegra_hdmi_codec_unregister(hdmi); |
1644 | |
1645 | tegra_output_exit(output: &hdmi->output); |
1646 | |
1647 | regulator_disable(regulator: hdmi->vdd); |
1648 | regulator_disable(regulator: hdmi->pll); |
1649 | regulator_disable(regulator: hdmi->hdmi); |
1650 | |
1651 | return 0; |
1652 | } |
1653 | |
1654 | static int tegra_hdmi_runtime_suspend(struct host1x_client *client) |
1655 | { |
1656 | struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client); |
1657 | struct device *dev = client->dev; |
1658 | int err; |
1659 | |
1660 | err = reset_control_assert(rstc: hdmi->rst); |
1661 | if (err < 0) { |
1662 | dev_err(dev, "failed to assert reset: %d\n" , err); |
1663 | return err; |
1664 | } |
1665 | |
1666 | usleep_range(min: 1000, max: 2000); |
1667 | |
1668 | clk_disable_unprepare(clk: hdmi->clk); |
1669 | pm_runtime_put_sync(dev); |
1670 | |
1671 | return 0; |
1672 | } |
1673 | |
1674 | static int tegra_hdmi_runtime_resume(struct host1x_client *client) |
1675 | { |
1676 | struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client); |
1677 | struct device *dev = client->dev; |
1678 | int err; |
1679 | |
1680 | err = pm_runtime_resume_and_get(dev); |
1681 | if (err < 0) { |
1682 | dev_err(dev, "failed to get runtime PM: %d\n" , err); |
1683 | return err; |
1684 | } |
1685 | |
1686 | err = clk_prepare_enable(clk: hdmi->clk); |
1687 | if (err < 0) { |
1688 | dev_err(dev, "failed to enable clock: %d\n" , err); |
1689 | goto put_rpm; |
1690 | } |
1691 | |
1692 | usleep_range(min: 1000, max: 2000); |
1693 | |
1694 | err = reset_control_deassert(rstc: hdmi->rst); |
1695 | if (err < 0) { |
1696 | dev_err(dev, "failed to deassert reset: %d\n" , err); |
1697 | goto disable_clk; |
1698 | } |
1699 | |
1700 | return 0; |
1701 | |
1702 | disable_clk: |
1703 | clk_disable_unprepare(clk: hdmi->clk); |
1704 | put_rpm: |
1705 | pm_runtime_put_sync(dev); |
1706 | return err; |
1707 | } |
1708 | |
1709 | static const struct host1x_client_ops hdmi_client_ops = { |
1710 | .init = tegra_hdmi_init, |
1711 | .exit = tegra_hdmi_exit, |
1712 | .suspend = tegra_hdmi_runtime_suspend, |
1713 | .resume = tegra_hdmi_runtime_resume, |
1714 | }; |
1715 | |
1716 | static const struct tegra_hdmi_config tegra20_hdmi_config = { |
1717 | .tmds = tegra20_tmds_config, |
1718 | .num_tmds = ARRAY_SIZE(tegra20_tmds_config), |
1719 | .fuse_override_offset = HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT, |
1720 | .fuse_override_value = 1 << 31, |
1721 | .has_sor_io_peak_current = false, |
1722 | .has_hda = false, |
1723 | .has_hbr = false, |
1724 | }; |
1725 | |
1726 | static const struct tegra_hdmi_config tegra30_hdmi_config = { |
1727 | .tmds = tegra30_tmds_config, |
1728 | .num_tmds = ARRAY_SIZE(tegra30_tmds_config), |
1729 | .fuse_override_offset = HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT, |
1730 | .fuse_override_value = 1 << 31, |
1731 | .has_sor_io_peak_current = false, |
1732 | .has_hda = true, |
1733 | .has_hbr = false, |
1734 | }; |
1735 | |
1736 | static const struct tegra_hdmi_config tegra114_hdmi_config = { |
1737 | .tmds = tegra114_tmds_config, |
1738 | .num_tmds = ARRAY_SIZE(tegra114_tmds_config), |
1739 | .fuse_override_offset = HDMI_NV_PDISP_SOR_PAD_CTLS0, |
1740 | .fuse_override_value = 1 << 31, |
1741 | .has_sor_io_peak_current = true, |
1742 | .has_hda = true, |
1743 | .has_hbr = true, |
1744 | }; |
1745 | |
1746 | static const struct tegra_hdmi_config tegra124_hdmi_config = { |
1747 | .tmds = tegra124_tmds_config, |
1748 | .num_tmds = ARRAY_SIZE(tegra124_tmds_config), |
1749 | .fuse_override_offset = HDMI_NV_PDISP_SOR_PAD_CTLS0, |
1750 | .fuse_override_value = 1 << 31, |
1751 | .has_sor_io_peak_current = true, |
1752 | .has_hda = true, |
1753 | .has_hbr = true, |
1754 | }; |
1755 | |
1756 | static const struct of_device_id tegra_hdmi_of_match[] = { |
1757 | { .compatible = "nvidia,tegra124-hdmi" , .data = &tegra124_hdmi_config }, |
1758 | { .compatible = "nvidia,tegra114-hdmi" , .data = &tegra114_hdmi_config }, |
1759 | { .compatible = "nvidia,tegra30-hdmi" , .data = &tegra30_hdmi_config }, |
1760 | { .compatible = "nvidia,tegra20-hdmi" , .data = &tegra20_hdmi_config }, |
1761 | { }, |
1762 | }; |
1763 | MODULE_DEVICE_TABLE(of, tegra_hdmi_of_match); |
1764 | |
1765 | static irqreturn_t tegra_hdmi_irq(int irq, void *data) |
1766 | { |
1767 | struct tegra_hdmi *hdmi = data; |
1768 | u32 value; |
1769 | |
1770 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_INT_STATUS); |
1771 | tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_INT_STATUS); |
1772 | |
1773 | if (value & INT_CODEC_SCRATCH0) { |
1774 | unsigned int format; |
1775 | u32 value; |
1776 | |
1777 | value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH0); |
1778 | |
1779 | if (value & SOR_AUDIO_HDA_CODEC_SCRATCH0_VALID) { |
1780 | format = value & SOR_AUDIO_HDA_CODEC_SCRATCH0_FMT_MASK; |
1781 | |
1782 | tegra_hda_parse_format(format, fmt: &hdmi->format); |
1783 | tegra_hdmi_reconfigure_audio(hdmi); |
1784 | } else { |
1785 | tegra_hdmi_disable_audio_infoframe(hdmi); |
1786 | tegra_hdmi_disable_audio(hdmi); |
1787 | } |
1788 | } |
1789 | |
1790 | return IRQ_HANDLED; |
1791 | } |
1792 | |
1793 | static int tegra_hdmi_probe(struct platform_device *pdev) |
1794 | { |
1795 | struct tegra_hdmi *hdmi; |
1796 | int err; |
1797 | |
1798 | hdmi = devm_kzalloc(dev: &pdev->dev, size: sizeof(*hdmi), GFP_KERNEL); |
1799 | if (!hdmi) |
1800 | return -ENOMEM; |
1801 | |
1802 | hdmi->config = of_device_get_match_data(dev: &pdev->dev); |
1803 | hdmi->dev = &pdev->dev; |
1804 | |
1805 | hdmi->audio_source = AUTO; |
1806 | hdmi->stereo = false; |
1807 | hdmi->dvi = false; |
1808 | |
1809 | mutex_init(&hdmi->audio_lock); |
1810 | |
1811 | hdmi->clk = devm_clk_get(dev: &pdev->dev, NULL); |
1812 | if (IS_ERR(ptr: hdmi->clk)) { |
1813 | dev_err(&pdev->dev, "failed to get clock\n" ); |
1814 | return PTR_ERR(ptr: hdmi->clk); |
1815 | } |
1816 | |
1817 | hdmi->rst = devm_reset_control_get(dev: &pdev->dev, id: "hdmi" ); |
1818 | if (IS_ERR(ptr: hdmi->rst)) { |
1819 | dev_err(&pdev->dev, "failed to get reset\n" ); |
1820 | return PTR_ERR(ptr: hdmi->rst); |
1821 | } |
1822 | |
1823 | hdmi->clk_parent = devm_clk_get(dev: &pdev->dev, id: "parent" ); |
1824 | if (IS_ERR(ptr: hdmi->clk_parent)) |
1825 | return PTR_ERR(ptr: hdmi->clk_parent); |
1826 | |
1827 | err = clk_set_parent(clk: hdmi->clk, parent: hdmi->clk_parent); |
1828 | if (err < 0) { |
1829 | dev_err(&pdev->dev, "failed to setup clocks: %d\n" , err); |
1830 | return err; |
1831 | } |
1832 | |
1833 | hdmi->hdmi = devm_regulator_get(dev: &pdev->dev, id: "hdmi" ); |
1834 | err = PTR_ERR_OR_ZERO(ptr: hdmi->hdmi); |
1835 | if (err) |
1836 | return dev_err_probe(dev: &pdev->dev, err, |
1837 | fmt: "failed to get HDMI regulator\n" ); |
1838 | |
1839 | hdmi->pll = devm_regulator_get(dev: &pdev->dev, id: "pll" ); |
1840 | err = PTR_ERR_OR_ZERO(ptr: hdmi->pll); |
1841 | if (err) |
1842 | return dev_err_probe(dev: &pdev->dev, err, |
1843 | fmt: "failed to get PLL regulator\n" ); |
1844 | |
1845 | hdmi->vdd = devm_regulator_get(dev: &pdev->dev, id: "vdd" ); |
1846 | err = PTR_ERR_OR_ZERO(ptr: hdmi->vdd); |
1847 | if (err) |
1848 | return dev_err_probe(dev: &pdev->dev, err, |
1849 | fmt: "failed to get VDD regulator\n" ); |
1850 | |
1851 | hdmi->output.dev = &pdev->dev; |
1852 | |
1853 | err = tegra_output_probe(output: &hdmi->output); |
1854 | if (err < 0) |
1855 | return err; |
1856 | |
1857 | hdmi->regs = devm_platform_ioremap_resource(pdev, index: 0); |
1858 | if (IS_ERR(ptr: hdmi->regs)) |
1859 | return PTR_ERR(ptr: hdmi->regs); |
1860 | |
1861 | err = platform_get_irq(pdev, 0); |
1862 | if (err < 0) |
1863 | return err; |
1864 | |
1865 | hdmi->irq = err; |
1866 | |
1867 | err = devm_request_irq(dev: hdmi->dev, irq: hdmi->irq, handler: tegra_hdmi_irq, irqflags: 0, |
1868 | devname: dev_name(dev: hdmi->dev), dev_id: hdmi); |
1869 | if (err < 0) { |
1870 | dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n" , |
1871 | hdmi->irq, err); |
1872 | return err; |
1873 | } |
1874 | |
1875 | platform_set_drvdata(pdev, data: hdmi); |
1876 | |
1877 | err = devm_pm_runtime_enable(dev: &pdev->dev); |
1878 | if (err) |
1879 | return err; |
1880 | |
1881 | err = devm_tegra_core_dev_init_opp_table_common(dev: &pdev->dev); |
1882 | if (err) |
1883 | return err; |
1884 | |
1885 | INIT_LIST_HEAD(list: &hdmi->client.list); |
1886 | hdmi->client.ops = &hdmi_client_ops; |
1887 | hdmi->client.dev = &pdev->dev; |
1888 | |
1889 | err = host1x_client_register(&hdmi->client); |
1890 | if (err < 0) { |
1891 | dev_err(&pdev->dev, "failed to register host1x client: %d\n" , |
1892 | err); |
1893 | return err; |
1894 | } |
1895 | |
1896 | return 0; |
1897 | } |
1898 | |
1899 | static void tegra_hdmi_remove(struct platform_device *pdev) |
1900 | { |
1901 | struct tegra_hdmi *hdmi = platform_get_drvdata(pdev); |
1902 | |
1903 | host1x_client_unregister(client: &hdmi->client); |
1904 | |
1905 | tegra_output_remove(output: &hdmi->output); |
1906 | } |
1907 | |
1908 | struct platform_driver tegra_hdmi_driver = { |
1909 | .driver = { |
1910 | .name = "tegra-hdmi" , |
1911 | .of_match_table = tegra_hdmi_of_match, |
1912 | }, |
1913 | .probe = tegra_hdmi_probe, |
1914 | .remove_new = tegra_hdmi_remove, |
1915 | }; |
1916 | |