aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2013-03-22 10:34:05 -0400
committerThierry Reding <thierry.reding@avionic-design.de>2013-04-22 06:39:11 -0400
commit4231c6b01af9f0f3eeca4b8d0d87125d78233b41 (patch)
tree479f497053b58427bfd8ae54a080113b23de79ff /drivers/gpu/host1x
parent6236451d83a720072053855fa63d51934024a707 (diff)
drm/tegra: Move drm to live under host1x
Make drm part of host1x driver. Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de> Tested-by: Thierry Reding <thierry.reding@avionic-design.de> Tested-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/gpu/host1x')
-rw-r--r--drivers/gpu/host1x/Kconfig2
-rw-r--r--drivers/gpu/host1x/Makefile5
-rw-r--r--drivers/gpu/host1x/drm/Kconfig23
-rw-r--r--drivers/gpu/host1x/drm/dc.c1193
-rw-r--r--drivers/gpu/host1x/drm/dc.h400
-rw-r--r--drivers/gpu/host1x/drm/drm.c217
-rw-r--r--drivers/gpu/host1x/drm/drm.h237
-rw-r--r--drivers/gpu/host1x/drm/fb.c52
-rw-r--r--drivers/gpu/host1x/drm/hdmi.c1312
-rw-r--r--drivers/gpu/host1x/drm/hdmi.h386
-rw-r--r--drivers/gpu/host1x/drm/host1x.c327
-rw-r--r--drivers/gpu/host1x/drm/output.c272
-rw-r--r--drivers/gpu/host1x/drm/rgb.c228
13 files changed, 4654 insertions, 0 deletions
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index 7d6bed222542..ccfd42b23606 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -19,4 +19,6 @@ config TEGRA_HOST1X_FIREWALL
19 19
20 If unsure, choose Y. 20 If unsure, choose Y.
21 21
22source "drivers/gpu/host1x/drm/Kconfig"
23
22endif 24endif
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 49fd5807b0e7..4761e8af7bdc 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -10,4 +10,9 @@ host1x-y = \
10 debug.o \ 10 debug.o \
11 hw/host1x01.o 11 hw/host1x01.o
12 12
13ccflags-y += -Iinclude/drm
14ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
15
16host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o drm/host1x.o
17host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
13obj-$(CONFIG_TEGRA_HOST1X) += host1x.o 18obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig
new file mode 100644
index 000000000000..8267691b7aa3
--- /dev/null
+++ b/drivers/gpu/host1x/drm/Kconfig
@@ -0,0 +1,23 @@
1config DRM_TEGRA
2 tristate "NVIDIA Tegra DRM"
3 depends on DRM && OF
4 select DRM_KMS_HELPER
5 select DRM_GEM_CMA_HELPER
6 select DRM_KMS_CMA_HELPER
7 select FB_CFB_FILLRECT
8 select FB_CFB_COPYAREA
9 select FB_CFB_IMAGEBLIT
10 help
11 Choose this option if you have an NVIDIA Tegra SoC.
12
13 To compile this driver as a module, choose M here: the module
14 will be called tegra-drm.
15
16if DRM_TEGRA
17
18config DRM_TEGRA_DEBUG
19 bool "NVIDIA Tegra DRM debug support"
20 help
21 Say yes here to enable debugging support.
22
23endif
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
new file mode 100644
index 000000000000..de94707b9dbe
--- /dev/null
+++ b/drivers/gpu/host1x/drm/dc.c
@@ -0,0 +1,1193 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/clk.h>
11#include <linux/debugfs.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15#include <linux/clk/tegra.h>
16
17#include "drm.h"
18#include "dc.h"
19
20struct tegra_plane {
21 struct drm_plane base;
22 unsigned int index;
23};
24
25static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
26{
27 return container_of(plane, struct tegra_plane, base);
28}
29
30static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
31 struct drm_framebuffer *fb, int crtc_x,
32 int crtc_y, unsigned int crtc_w,
33 unsigned int crtc_h, uint32_t src_x,
34 uint32_t src_y, uint32_t src_w, uint32_t src_h)
35{
36 struct tegra_plane *p = to_tegra_plane(plane);
37 struct tegra_dc *dc = to_tegra_dc(crtc);
38 struct tegra_dc_window window;
39 unsigned int i;
40
41 memset(&window, 0, sizeof(window));
42 window.src.x = src_x >> 16;
43 window.src.y = src_y >> 16;
44 window.src.w = src_w >> 16;
45 window.src.h = src_h >> 16;
46 window.dst.x = crtc_x;
47 window.dst.y = crtc_y;
48 window.dst.w = crtc_w;
49 window.dst.h = crtc_h;
50 window.format = tegra_dc_format(fb->pixel_format);
51 window.bits_per_pixel = fb->bits_per_pixel;
52
53 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
54 struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
55
56 window.base[i] = gem->paddr + fb->offsets[i];
57
58 /*
59 * Tegra doesn't support different strides for U and V planes
60 * so we display a warning if the user tries to display a
61 * framebuffer with such a configuration.
62 */
63 if (i >= 2) {
64 if (fb->pitches[i] != window.stride[1])
65 DRM_ERROR("unsupported UV-plane configuration\n");
66 } else {
67 window.stride[i] = fb->pitches[i];
68 }
69 }
70
71 return tegra_dc_setup_window(dc, p->index, &window);
72}
73
74static int tegra_plane_disable(struct drm_plane *plane)
75{
76 struct tegra_dc *dc = to_tegra_dc(plane->crtc);
77 struct tegra_plane *p = to_tegra_plane(plane);
78 unsigned long value;
79
80 value = WINDOW_A_SELECT << p->index;
81 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
82
83 value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
84 value &= ~WIN_ENABLE;
85 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
86
87 tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL);
88 tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL);
89
90 return 0;
91}
92
93static void tegra_plane_destroy(struct drm_plane *plane)
94{
95 tegra_plane_disable(plane);
96 drm_plane_cleanup(plane);
97}
98
99static const struct drm_plane_funcs tegra_plane_funcs = {
100 .update_plane = tegra_plane_update,
101 .disable_plane = tegra_plane_disable,
102 .destroy = tegra_plane_destroy,
103};
104
105static const uint32_t plane_formats[] = {
106 DRM_FORMAT_XRGB8888,
107 DRM_FORMAT_UYVY,
108 DRM_FORMAT_YUV420,
109 DRM_FORMAT_YUV422,
110};
111
112static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
113{
114 unsigned int i;
115 int err = 0;
116
117 for (i = 0; i < 2; i++) {
118 struct tegra_plane *plane;
119
120 plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
121 if (!plane)
122 return -ENOMEM;
123
124 plane->index = 1 + i;
125
126 err = drm_plane_init(drm, &plane->base, 1 << dc->pipe,
127 &tegra_plane_funcs, plane_formats,
128 ARRAY_SIZE(plane_formats), false);
129 if (err < 0)
130 return err;
131 }
132
133 return 0;
134}
135
136static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
137 struct drm_framebuffer *fb)
138{
139 struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, 0);
140 unsigned long value;
141
142 tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
143
144 value = fb->offsets[0] + y * fb->pitches[0] +
145 x * fb->bits_per_pixel / 8;
146
147 tegra_dc_writel(dc, gem->paddr + value, DC_WINBUF_START_ADDR);
148 tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
149
150 value = GENERAL_UPDATE | WIN_A_UPDATE;
151 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
152
153 value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
154 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
155
156 return 0;
157}
158
159void tegra_dc_enable_vblank(struct tegra_dc *dc)
160{
161 unsigned long value, flags;
162
163 spin_lock_irqsave(&dc->lock, flags);
164
165 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
166 value |= VBLANK_INT;
167 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
168
169 spin_unlock_irqrestore(&dc->lock, flags);
170}
171
172void tegra_dc_disable_vblank(struct tegra_dc *dc)
173{
174 unsigned long value, flags;
175
176 spin_lock_irqsave(&dc->lock, flags);
177
178 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
179 value &= ~VBLANK_INT;
180 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
181
182 spin_unlock_irqrestore(&dc->lock, flags);
183}
184
185static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
186{
187 struct drm_device *drm = dc->base.dev;
188 struct drm_crtc *crtc = &dc->base;
189 struct drm_gem_cma_object *gem;
190 unsigned long flags, base;
191
192 if (!dc->event)
193 return;
194
195 gem = drm_fb_cma_get_gem_obj(crtc->fb, 0);
196
197 /* check if new start address has been latched */
198 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
199 base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
200 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
201
202 if (base == gem->paddr + crtc->fb->offsets[0]) {
203 spin_lock_irqsave(&drm->event_lock, flags);
204 drm_send_vblank_event(drm, dc->pipe, dc->event);
205 drm_vblank_put(drm, dc->pipe);
206 dc->event = NULL;
207 spin_unlock_irqrestore(&drm->event_lock, flags);
208 }
209}
210
211void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
212{
213 struct tegra_dc *dc = to_tegra_dc(crtc);
214 struct drm_device *drm = crtc->dev;
215 unsigned long flags;
216
217 spin_lock_irqsave(&drm->event_lock, flags);
218
219 if (dc->event && dc->event->base.file_priv == file) {
220 dc->event->base.destroy(&dc->event->base);
221 drm_vblank_put(drm, dc->pipe);
222 dc->event = NULL;
223 }
224
225 spin_unlock_irqrestore(&drm->event_lock, flags);
226}
227
228static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
229 struct drm_pending_vblank_event *event)
230{
231 struct tegra_dc *dc = to_tegra_dc(crtc);
232 struct drm_device *drm = crtc->dev;
233
234 if (dc->event)
235 return -EBUSY;
236
237 if (event) {
238 event->pipe = dc->pipe;
239 dc->event = event;
240 drm_vblank_get(drm, dc->pipe);
241 }
242
243 tegra_dc_set_base(dc, 0, 0, fb);
244 crtc->fb = fb;
245
246 return 0;
247}
248
249static const struct drm_crtc_funcs tegra_crtc_funcs = {
250 .page_flip = tegra_dc_page_flip,
251 .set_config = drm_crtc_helper_set_config,
252 .destroy = drm_crtc_cleanup,
253};
254
255static void tegra_crtc_disable(struct drm_crtc *crtc)
256{
257 struct drm_device *drm = crtc->dev;
258 struct drm_plane *plane;
259
260 list_for_each_entry(plane, &drm->mode_config.plane_list, head) {
261 if (plane->crtc == crtc) {
262 tegra_plane_disable(plane);
263 plane->crtc = NULL;
264
265 if (plane->fb) {
266 drm_framebuffer_unreference(plane->fb);
267 plane->fb = NULL;
268 }
269 }
270 }
271}
272
273static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
274 const struct drm_display_mode *mode,
275 struct drm_display_mode *adjusted)
276{
277 return true;
278}
279
280static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
281 unsigned int bpp)
282{
283 fixed20_12 outf = dfixed_init(out);
284 fixed20_12 inf = dfixed_init(in);
285 u32 dda_inc;
286 int max;
287
288 if (v)
289 max = 15;
290 else {
291 switch (bpp) {
292 case 2:
293 max = 8;
294 break;
295
296 default:
297 WARN_ON_ONCE(1);
298 /* fallthrough */
299 case 4:
300 max = 4;
301 break;
302 }
303 }
304
305 outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
306 inf.full -= dfixed_const(1);
307
308 dda_inc = dfixed_div(inf, outf);
309 dda_inc = min_t(u32, dda_inc, dfixed_const(max));
310
311 return dda_inc;
312}
313
314static inline u32 compute_initial_dda(unsigned int in)
315{
316 fixed20_12 inf = dfixed_init(in);
317 return dfixed_frac(inf);
318}
319
320static int tegra_dc_set_timings(struct tegra_dc *dc,
321 struct drm_display_mode *mode)
322{
323 /* TODO: For HDMI compliance, h & v ref_to_sync should be set to 1 */
324 unsigned int h_ref_to_sync = 0;
325 unsigned int v_ref_to_sync = 0;
326 unsigned long value;
327
328 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
329
330 value = (v_ref_to_sync << 16) | h_ref_to_sync;
331 tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
332
333 value = ((mode->vsync_end - mode->vsync_start) << 16) |
334 ((mode->hsync_end - mode->hsync_start) << 0);
335 tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
336
337 value = ((mode->vtotal - mode->vsync_end) << 16) |
338 ((mode->htotal - mode->hsync_end) << 0);
339 tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
340
341 value = ((mode->vsync_start - mode->vdisplay) << 16) |
342 ((mode->hsync_start - mode->hdisplay) << 0);
343 tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
344
345 value = (mode->vdisplay << 16) | mode->hdisplay;
346 tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
347
348 return 0;
349}
350
351static int tegra_crtc_setup_clk(struct drm_crtc *crtc,
352 struct drm_display_mode *mode,
353 unsigned long *div)
354{
355 unsigned long pclk = mode->clock * 1000, rate;
356 struct tegra_dc *dc = to_tegra_dc(crtc);
357 struct tegra_output *output = NULL;
358 struct drm_encoder *encoder;
359 long err;
360
361 list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head)
362 if (encoder->crtc == crtc) {
363 output = encoder_to_output(encoder);
364 break;
365 }
366
367 if (!output)
368 return -ENODEV;
369
370 /*
371 * This assumes that the display controller will divide its parent
372 * clock by 2 to generate the pixel clock.
373 */
374 err = tegra_output_setup_clock(output, dc->clk, pclk * 2);
375 if (err < 0) {
376 dev_err(dc->dev, "failed to setup clock: %ld\n", err);
377 return err;
378 }
379
380 rate = clk_get_rate(dc->clk);
381 *div = (rate * 2 / pclk) - 2;
382
383 DRM_DEBUG_KMS("rate: %lu, div: %lu\n", rate, *div);
384
385 return 0;
386}
387
388static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
389{
390 switch (format) {
391 case WIN_COLOR_DEPTH_YCbCr422:
392 case WIN_COLOR_DEPTH_YUV422:
393 if (planar)
394 *planar = false;
395
396 return true;
397
398 case WIN_COLOR_DEPTH_YCbCr420P:
399 case WIN_COLOR_DEPTH_YUV420P:
400 case WIN_COLOR_DEPTH_YCbCr422P:
401 case WIN_COLOR_DEPTH_YUV422P:
402 case WIN_COLOR_DEPTH_YCbCr422R:
403 case WIN_COLOR_DEPTH_YUV422R:
404 case WIN_COLOR_DEPTH_YCbCr422RA:
405 case WIN_COLOR_DEPTH_YUV422RA:
406 if (planar)
407 *planar = true;
408
409 return true;
410 }
411
412 return false;
413}
414
415int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
416 const struct tegra_dc_window *window)
417{
418 unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
419 unsigned long value;
420 bool yuv, planar;
421
422 /*
423 * For YUV planar modes, the number of bytes per pixel takes into
424 * account only the luma component and therefore is 1.
425 */
426 yuv = tegra_dc_format_is_yuv(window->format, &planar);
427 if (!yuv)
428 bpp = window->bits_per_pixel / 8;
429 else
430 bpp = planar ? 1 : 2;
431
432 value = WINDOW_A_SELECT << index;
433 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
434
435 tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
436 tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
437
438 value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
439 tegra_dc_writel(dc, value, DC_WIN_POSITION);
440
441 value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
442 tegra_dc_writel(dc, value, DC_WIN_SIZE);
443
444 h_offset = window->src.x * bpp;
445 v_offset = window->src.y;
446 h_size = window->src.w * bpp;
447 v_size = window->src.h;
448
449 value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
450 tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
451
452 /*
453 * For DDA computations the number of bytes per pixel for YUV planar
454 * modes needs to take into account all Y, U and V components.
455 */
456 if (yuv && planar)
457 bpp = 2;
458
459 h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
460 v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
461
462 value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
463 tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
464
465 h_dda = compute_initial_dda(window->src.x);
466 v_dda = compute_initial_dda(window->src.y);
467
468 tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
469 tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
470
471 tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
472 tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
473
474 tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
475
476 if (yuv && planar) {
477 tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
478 tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
479 value = window->stride[1] << 16 | window->stride[0];
480 tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
481 } else {
482 tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
483 }
484
485 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
486 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
487
488 value = WIN_ENABLE;
489
490 if (yuv) {
491 /* setup default colorspace conversion coefficients */
492 tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
493 tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
494 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
495 tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
496 tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
497 tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
498 tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
499 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
500
501 value |= CSC_ENABLE;
502 } else if (window->bits_per_pixel < 24) {
503 value |= COLOR_EXPAND;
504 }
505
506 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
507
508 /*
509 * Disable blending and assume Window A is the bottom-most window,
510 * Window C is the top-most window and Window B is in the middle.
511 */
512 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
513 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
514
515 switch (index) {
516 case 0:
517 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
518 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
519 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
520 break;
521
522 case 1:
523 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
524 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
525 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
526 break;
527
528 case 2:
529 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
530 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
531 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
532 break;
533 }
534
535 tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL);
536 tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL);
537
538 return 0;
539}
540
541unsigned int tegra_dc_format(uint32_t format)
542{
543 switch (format) {
544 case DRM_FORMAT_XRGB8888:
545 return WIN_COLOR_DEPTH_B8G8R8A8;
546
547 case DRM_FORMAT_RGB565:
548 return WIN_COLOR_DEPTH_B5G6R5;
549
550 case DRM_FORMAT_UYVY:
551 return WIN_COLOR_DEPTH_YCbCr422;
552
553 case DRM_FORMAT_YUV420:
554 return WIN_COLOR_DEPTH_YCbCr420P;
555
556 case DRM_FORMAT_YUV422:
557 return WIN_COLOR_DEPTH_YCbCr422P;
558
559 default:
560 break;
561 }
562
563 WARN(1, "unsupported pixel format %u, using default\n", format);
564 return WIN_COLOR_DEPTH_B8G8R8A8;
565}
566
567static int tegra_crtc_mode_set(struct drm_crtc *crtc,
568 struct drm_display_mode *mode,
569 struct drm_display_mode *adjusted,
570 int x, int y, struct drm_framebuffer *old_fb)
571{
572 struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(crtc->fb, 0);
573 struct tegra_dc *dc = to_tegra_dc(crtc);
574 struct tegra_dc_window window;
575 unsigned long div, value;
576 int err;
577
578 drm_vblank_pre_modeset(crtc->dev, dc->pipe);
579
580 err = tegra_crtc_setup_clk(crtc, mode, &div);
581 if (err) {
582 dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
583 return err;
584 }
585
586 /* program display mode */
587 tegra_dc_set_timings(dc, mode);
588
589 value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
590 tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
591
592 value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
593 value &= ~LVS_OUTPUT_POLARITY_LOW;
594 value &= ~LHS_OUTPUT_POLARITY_LOW;
595 tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
596
597 value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
598 DISP_ORDER_RED_BLUE;
599 tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
600
601 tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
602
603 value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
604 tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
605
606 /* setup window parameters */
607 memset(&window, 0, sizeof(window));
608 window.src.x = 0;
609 window.src.y = 0;
610 window.src.w = mode->hdisplay;
611 window.src.h = mode->vdisplay;
612 window.dst.x = 0;
613 window.dst.y = 0;
614 window.dst.w = mode->hdisplay;
615 window.dst.h = mode->vdisplay;
616 window.format = tegra_dc_format(crtc->fb->pixel_format);
617 window.bits_per_pixel = crtc->fb->bits_per_pixel;
618 window.stride[0] = crtc->fb->pitches[0];
619 window.base[0] = gem->paddr;
620
621 err = tegra_dc_setup_window(dc, 0, &window);
622 if (err < 0)
623 dev_err(dc->dev, "failed to enable root plane\n");
624
625 return 0;
626}
627
628static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
629 struct drm_framebuffer *old_fb)
630{
631 struct tegra_dc *dc = to_tegra_dc(crtc);
632
633 return tegra_dc_set_base(dc, x, y, crtc->fb);
634}
635
636static void tegra_crtc_prepare(struct drm_crtc *crtc)
637{
638 struct tegra_dc *dc = to_tegra_dc(crtc);
639 unsigned int syncpt;
640 unsigned long value;
641
642 /* hardware initialization */
643 tegra_periph_reset_deassert(dc->clk);
644 usleep_range(10000, 20000);
645
646 if (dc->pipe)
647 syncpt = SYNCPT_VBLANK1;
648 else
649 syncpt = SYNCPT_VBLANK0;
650
651 /* initialize display controller */
652 tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
653 tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
654
655 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
656 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
657
658 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
659 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
660 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
661
662 value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
663 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
664 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
665
666 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
667 value |= DISP_CTRL_MODE_C_DISPLAY;
668 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
669
670 /* initialize timer */
671 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
672 WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
673 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
674
675 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
676 WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
677 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
678
679 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
680 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
681
682 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
683 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
684}
685
686static void tegra_crtc_commit(struct drm_crtc *crtc)
687{
688 struct tegra_dc *dc = to_tegra_dc(crtc);
689 unsigned long value;
690
691 value = GENERAL_UPDATE | WIN_A_UPDATE;
692 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
693
694 value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
695 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
696
697 drm_vblank_post_modeset(crtc->dev, dc->pipe);
698}
699
700static void tegra_crtc_load_lut(struct drm_crtc *crtc)
701{
702}
703
704static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
705 .disable = tegra_crtc_disable,
706 .mode_fixup = tegra_crtc_mode_fixup,
707 .mode_set = tegra_crtc_mode_set,
708 .mode_set_base = tegra_crtc_mode_set_base,
709 .prepare = tegra_crtc_prepare,
710 .commit = tegra_crtc_commit,
711 .load_lut = tegra_crtc_load_lut,
712};
713
714static irqreturn_t tegra_dc_irq(int irq, void *data)
715{
716 struct tegra_dc *dc = data;
717 unsigned long status;
718
719 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
720 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
721
722 if (status & FRAME_END_INT) {
723 /*
724 dev_dbg(dc->dev, "%s(): frame end\n", __func__);
725 */
726 }
727
728 if (status & VBLANK_INT) {
729 /*
730 dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
731 */
732 drm_handle_vblank(dc->base.dev, dc->pipe);
733 tegra_dc_finish_page_flip(dc);
734 }
735
736 if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
737 /*
738 dev_dbg(dc->dev, "%s(): underflow\n", __func__);
739 */
740 }
741
742 return IRQ_HANDLED;
743}
744
745static int tegra_dc_show_regs(struct seq_file *s, void *data)
746{
747 struct drm_info_node *node = s->private;
748 struct tegra_dc *dc = node->info_ent->data;
749
750#define DUMP_REG(name) \
751 seq_printf(s, "%-40s %#05x %08lx\n", #name, name, \
752 tegra_dc_readl(dc, name))
753
754 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT);
755 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
756 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR);
757 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT);
758 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL);
759 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR);
760 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT);
761 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL);
762 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR);
763 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT);
764 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL);
765 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR);
766 DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC);
767 DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
768 DUMP_REG(DC_CMD_DISPLAY_COMMAND);
769 DUMP_REG(DC_CMD_SIGNAL_RAISE);
770 DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
771 DUMP_REG(DC_CMD_INT_STATUS);
772 DUMP_REG(DC_CMD_INT_MASK);
773 DUMP_REG(DC_CMD_INT_ENABLE);
774 DUMP_REG(DC_CMD_INT_TYPE);
775 DUMP_REG(DC_CMD_INT_POLARITY);
776 DUMP_REG(DC_CMD_SIGNAL_RAISE1);
777 DUMP_REG(DC_CMD_SIGNAL_RAISE2);
778 DUMP_REG(DC_CMD_SIGNAL_RAISE3);
779 DUMP_REG(DC_CMD_STATE_ACCESS);
780 DUMP_REG(DC_CMD_STATE_CONTROL);
781 DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
782 DUMP_REG(DC_CMD_REG_ACT_CONTROL);
783 DUMP_REG(DC_COM_CRC_CONTROL);
784 DUMP_REG(DC_COM_CRC_CHECKSUM);
785 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0));
786 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1));
787 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2));
788 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3));
789 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0));
790 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1));
791 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2));
792 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3));
793 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0));
794 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1));
795 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2));
796 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3));
797 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0));
798 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1));
799 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2));
800 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3));
801 DUMP_REG(DC_COM_PIN_INPUT_DATA(0));
802 DUMP_REG(DC_COM_PIN_INPUT_DATA(1));
803 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0));
804 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1));
805 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2));
806 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3));
807 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4));
808 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5));
809 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6));
810 DUMP_REG(DC_COM_PIN_MISC_CONTROL);
811 DUMP_REG(DC_COM_PIN_PM0_CONTROL);
812 DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE);
813 DUMP_REG(DC_COM_PIN_PM1_CONTROL);
814 DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE);
815 DUMP_REG(DC_COM_SPI_CONTROL);
816 DUMP_REG(DC_COM_SPI_START_BYTE);
817 DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB);
818 DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD);
819 DUMP_REG(DC_COM_HSPI_CS_DC);
820 DUMP_REG(DC_COM_SCRATCH_REGISTER_A);
821 DUMP_REG(DC_COM_SCRATCH_REGISTER_B);
822 DUMP_REG(DC_COM_GPIO_CTRL);
823 DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER);
824 DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED);
825 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
826 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
827 DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
828 DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY);
829 DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
830 DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
831 DUMP_REG(DC_DISP_REF_TO_SYNC);
832 DUMP_REG(DC_DISP_SYNC_WIDTH);
833 DUMP_REG(DC_DISP_BACK_PORCH);
834 DUMP_REG(DC_DISP_ACTIVE);
835 DUMP_REG(DC_DISP_FRONT_PORCH);
836 DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
837 DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
838 DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
839 DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
840 DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
841 DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
842 DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
843 DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
844 DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
845 DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
846 DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
847 DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
848 DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
849 DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
850 DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
851 DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
852 DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
853 DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
854 DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
855 DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
856 DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
857 DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
858 DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
859 DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
860 DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
861 DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
862 DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
863 DUMP_REG(DC_DISP_M0_CONTROL);
864 DUMP_REG(DC_DISP_M1_CONTROL);
865 DUMP_REG(DC_DISP_DI_CONTROL);
866 DUMP_REG(DC_DISP_PP_CONTROL);
867 DUMP_REG(DC_DISP_PP_SELECT_A);
868 DUMP_REG(DC_DISP_PP_SELECT_B);
869 DUMP_REG(DC_DISP_PP_SELECT_C);
870 DUMP_REG(DC_DISP_PP_SELECT_D);
871 DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
872 DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
873 DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
874 DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
875 DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
876 DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
877 DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
878 DUMP_REG(DC_DISP_BORDER_COLOR);
879 DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
880 DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
881 DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
882 DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
883 DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
884 DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
885 DUMP_REG(DC_DISP_CURSOR_START_ADDR);
886 DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
887 DUMP_REG(DC_DISP_CURSOR_POSITION);
888 DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
889 DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
890 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
891 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
892 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
893 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
894 DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
895 DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
896 DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
897 DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST);
898 DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
899 DUMP_REG(DC_DISP_DAC_CRT_CTRL);
900 DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
901 DUMP_REG(DC_DISP_SD_CONTROL);
902 DUMP_REG(DC_DISP_SD_CSC_COEFF);
903 DUMP_REG(DC_DISP_SD_LUT(0));
904 DUMP_REG(DC_DISP_SD_LUT(1));
905 DUMP_REG(DC_DISP_SD_LUT(2));
906 DUMP_REG(DC_DISP_SD_LUT(3));
907 DUMP_REG(DC_DISP_SD_LUT(4));
908 DUMP_REG(DC_DISP_SD_LUT(5));
909 DUMP_REG(DC_DISP_SD_LUT(6));
910 DUMP_REG(DC_DISP_SD_LUT(7));
911 DUMP_REG(DC_DISP_SD_LUT(8));
912 DUMP_REG(DC_DISP_SD_FLICKER_CONTROL);
913 DUMP_REG(DC_DISP_DC_PIXEL_COUNT);
914 DUMP_REG(DC_DISP_SD_HISTOGRAM(0));
915 DUMP_REG(DC_DISP_SD_HISTOGRAM(1));
916 DUMP_REG(DC_DISP_SD_HISTOGRAM(2));
917 DUMP_REG(DC_DISP_SD_HISTOGRAM(3));
918 DUMP_REG(DC_DISP_SD_HISTOGRAM(4));
919 DUMP_REG(DC_DISP_SD_HISTOGRAM(5));
920 DUMP_REG(DC_DISP_SD_HISTOGRAM(6));
921 DUMP_REG(DC_DISP_SD_HISTOGRAM(7));
922 DUMP_REG(DC_DISP_SD_BL_TF(0));
923 DUMP_REG(DC_DISP_SD_BL_TF(1));
924 DUMP_REG(DC_DISP_SD_BL_TF(2));
925 DUMP_REG(DC_DISP_SD_BL_TF(3));
926 DUMP_REG(DC_DISP_SD_BL_CONTROL);
927 DUMP_REG(DC_DISP_SD_HW_K_VALUES);
928 DUMP_REG(DC_DISP_SD_MAN_K_VALUES);
929 DUMP_REG(DC_WIN_WIN_OPTIONS);
930 DUMP_REG(DC_WIN_BYTE_SWAP);
931 DUMP_REG(DC_WIN_BUFFER_CONTROL);
932 DUMP_REG(DC_WIN_COLOR_DEPTH);
933 DUMP_REG(DC_WIN_POSITION);
934 DUMP_REG(DC_WIN_SIZE);
935 DUMP_REG(DC_WIN_PRESCALED_SIZE);
936 DUMP_REG(DC_WIN_H_INITIAL_DDA);
937 DUMP_REG(DC_WIN_V_INITIAL_DDA);
938 DUMP_REG(DC_WIN_DDA_INC);
939 DUMP_REG(DC_WIN_LINE_STRIDE);
940 DUMP_REG(DC_WIN_BUF_STRIDE);
941 DUMP_REG(DC_WIN_UV_BUF_STRIDE);
942 DUMP_REG(DC_WIN_BUFFER_ADDR_MODE);
943 DUMP_REG(DC_WIN_DV_CONTROL);
944 DUMP_REG(DC_WIN_BLEND_NOKEY);
945 DUMP_REG(DC_WIN_BLEND_1WIN);
946 DUMP_REG(DC_WIN_BLEND_2WIN_X);
947 DUMP_REG(DC_WIN_BLEND_2WIN_Y);
948 DUMP_REG(DC_WIN_BLEND_3WIN_XY);
949 DUMP_REG(DC_WIN_HP_FETCH_CONTROL);
950 DUMP_REG(DC_WINBUF_START_ADDR);
951 DUMP_REG(DC_WINBUF_START_ADDR_NS);
952 DUMP_REG(DC_WINBUF_START_ADDR_U);
953 DUMP_REG(DC_WINBUF_START_ADDR_U_NS);
954 DUMP_REG(DC_WINBUF_START_ADDR_V);
955 DUMP_REG(DC_WINBUF_START_ADDR_V_NS);
956 DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
957 DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS);
958 DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
959 DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS);
960 DUMP_REG(DC_WINBUF_UFLOW_STATUS);
961 DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS);
962 DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS);
963 DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS);
964
965#undef DUMP_REG
966
967 return 0;
968}
969
970static struct drm_info_list debugfs_files[] = {
971 { "regs", tegra_dc_show_regs, 0, NULL },
972};
973
974static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
975{
976 unsigned int i;
977 char *name;
978 int err;
979
980 name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
981 dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
982 kfree(name);
983
984 if (!dc->debugfs)
985 return -ENOMEM;
986
987 dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
988 GFP_KERNEL);
989 if (!dc->debugfs_files) {
990 err = -ENOMEM;
991 goto remove;
992 }
993
994 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
995 dc->debugfs_files[i].data = dc;
996
997 err = drm_debugfs_create_files(dc->debugfs_files,
998 ARRAY_SIZE(debugfs_files),
999 dc->debugfs, minor);
1000 if (err < 0)
1001 goto free;
1002
1003 dc->minor = minor;
1004
1005 return 0;
1006
1007free:
1008 kfree(dc->debugfs_files);
1009 dc->debugfs_files = NULL;
1010remove:
1011 debugfs_remove(dc->debugfs);
1012 dc->debugfs = NULL;
1013
1014 return err;
1015}
1016
1017static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
1018{
1019 drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
1020 dc->minor);
1021 dc->minor = NULL;
1022
1023 kfree(dc->debugfs_files);
1024 dc->debugfs_files = NULL;
1025
1026 debugfs_remove(dc->debugfs);
1027 dc->debugfs = NULL;
1028
1029 return 0;
1030}
1031
1032static int tegra_dc_drm_init(struct host1x_client *client,
1033 struct drm_device *drm)
1034{
1035 struct tegra_dc *dc = host1x_client_to_dc(client);
1036 int err;
1037
1038 dc->pipe = drm->mode_config.num_crtc;
1039
1040 drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
1041 drm_mode_crtc_set_gamma_size(&dc->base, 256);
1042 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1043
1044 err = tegra_dc_rgb_init(drm, dc);
1045 if (err < 0 && err != -ENODEV) {
1046 dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
1047 return err;
1048 }
1049
1050 err = tegra_dc_add_planes(drm, dc);
1051 if (err < 0)
1052 return err;
1053
1054 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1055 err = tegra_dc_debugfs_init(dc, drm->primary);
1056 if (err < 0)
1057 dev_err(dc->dev, "debugfs setup failed: %d\n", err);
1058 }
1059
1060 err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
1061 dev_name(dc->dev), dc);
1062 if (err < 0) {
1063 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
1064 err);
1065 return err;
1066 }
1067
1068 return 0;
1069}
1070
1071static int tegra_dc_drm_exit(struct host1x_client *client)
1072{
1073 struct tegra_dc *dc = host1x_client_to_dc(client);
1074 int err;
1075
1076 devm_free_irq(dc->dev, dc->irq, dc);
1077
1078 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1079 err = tegra_dc_debugfs_exit(dc);
1080 if (err < 0)
1081 dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
1082 }
1083
1084 err = tegra_dc_rgb_exit(dc);
1085 if (err) {
1086 dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
1087 return err;
1088 }
1089
1090 return 0;
1091}
1092
1093static const struct host1x_client_ops dc_client_ops = {
1094 .drm_init = tegra_dc_drm_init,
1095 .drm_exit = tegra_dc_drm_exit,
1096};
1097
1098static int tegra_dc_probe(struct platform_device *pdev)
1099{
1100 struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
1101 struct resource *regs;
1102 struct tegra_dc *dc;
1103 int err;
1104
1105 dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
1106 if (!dc)
1107 return -ENOMEM;
1108
1109 spin_lock_init(&dc->lock);
1110 INIT_LIST_HEAD(&dc->list);
1111 dc->dev = &pdev->dev;
1112
1113 dc->clk = devm_clk_get(&pdev->dev, NULL);
1114 if (IS_ERR(dc->clk)) {
1115 dev_err(&pdev->dev, "failed to get clock\n");
1116 return PTR_ERR(dc->clk);
1117 }
1118
1119 err = clk_prepare_enable(dc->clk);
1120 if (err < 0)
1121 return err;
1122
1123 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1124 if (!regs) {
1125 dev_err(&pdev->dev, "failed to get registers\n");
1126 return -ENXIO;
1127 }
1128
1129 dc->regs = devm_ioremap_resource(&pdev->dev, regs);
1130 if (IS_ERR(dc->regs))
1131 return PTR_ERR(dc->regs);
1132
1133 dc->irq = platform_get_irq(pdev, 0);
1134 if (dc->irq < 0) {
1135 dev_err(&pdev->dev, "failed to get IRQ\n");
1136 return -ENXIO;
1137 }
1138
1139 INIT_LIST_HEAD(&dc->client.list);
1140 dc->client.ops = &dc_client_ops;
1141 dc->client.dev = &pdev->dev;
1142
1143 err = tegra_dc_rgb_probe(dc);
1144 if (err < 0 && err != -ENODEV) {
1145 dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
1146 return err;
1147 }
1148
1149 err = host1x_register_client(host1x, &dc->client);
1150 if (err < 0) {
1151 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1152 err);
1153 return err;
1154 }
1155
1156 platform_set_drvdata(pdev, dc);
1157
1158 return 0;
1159}
1160
1161static int tegra_dc_remove(struct platform_device *pdev)
1162{
1163 struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
1164 struct tegra_dc *dc = platform_get_drvdata(pdev);
1165 int err;
1166
1167 err = host1x_unregister_client(host1x, &dc->client);
1168 if (err < 0) {
1169 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1170 err);
1171 return err;
1172 }
1173
1174 clk_disable_unprepare(dc->clk);
1175
1176 return 0;
1177}
1178
1179static struct of_device_id tegra_dc_of_match[] = {
1180 { .compatible = "nvidia,tegra30-dc", },
1181 { .compatible = "nvidia,tegra20-dc", },
1182 { },
1183};
1184
1185struct platform_driver tegra_dc_driver = {
1186 .driver = {
1187 .name = "tegra-dc",
1188 .owner = THIS_MODULE,
1189 .of_match_table = tegra_dc_of_match,
1190 },
1191 .probe = tegra_dc_probe,
1192 .remove = tegra_dc_remove,
1193};
diff --git a/drivers/gpu/host1x/drm/dc.h b/drivers/gpu/host1x/drm/dc.h
new file mode 100644
index 000000000000..79eaec9aac77
--- /dev/null
+++ b/drivers/gpu/host1x/drm/dc.h
@@ -0,0 +1,400 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#ifndef TEGRA_DC_H
11#define TEGRA_DC_H 1
12
13#define DC_CMD_GENERAL_INCR_SYNCPT 0x000
14#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001
15#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR 0x002
16#define DC_CMD_WIN_A_INCR_SYNCPT 0x008
17#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL 0x009
18#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR 0x00a
19#define DC_CMD_WIN_B_INCR_SYNCPT 0x010
20#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL 0x011
21#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR 0x012
22#define DC_CMD_WIN_C_INCR_SYNCPT 0x018
23#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL 0x019
24#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a
25#define DC_CMD_CONT_SYNCPT_VSYNC 0x028
26#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
27#define DC_CMD_DISPLAY_COMMAND 0x032
28#define DISP_CTRL_MODE_STOP (0 << 5)
29#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
30#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
31#define DC_CMD_SIGNAL_RAISE 0x033
32#define DC_CMD_DISPLAY_POWER_CONTROL 0x036
33#define PW0_ENABLE (1 << 0)
34#define PW1_ENABLE (1 << 2)
35#define PW2_ENABLE (1 << 4)
36#define PW3_ENABLE (1 << 6)
37#define PW4_ENABLE (1 << 8)
38#define PM0_ENABLE (1 << 16)
39#define PM1_ENABLE (1 << 18)
40
41#define DC_CMD_INT_STATUS 0x037
42#define DC_CMD_INT_MASK 0x038
43#define DC_CMD_INT_ENABLE 0x039
44#define DC_CMD_INT_TYPE 0x03a
45#define DC_CMD_INT_POLARITY 0x03b
46#define CTXSW_INT (1 << 0)
47#define FRAME_END_INT (1 << 1)
48#define VBLANK_INT (1 << 2)
49#define WIN_A_UF_INT (1 << 8)
50#define WIN_B_UF_INT (1 << 9)
51#define WIN_C_UF_INT (1 << 10)
52#define WIN_A_OF_INT (1 << 14)
53#define WIN_B_OF_INT (1 << 15)
54#define WIN_C_OF_INT (1 << 16)
55
56#define DC_CMD_SIGNAL_RAISE1 0x03c
57#define DC_CMD_SIGNAL_RAISE2 0x03d
58#define DC_CMD_SIGNAL_RAISE3 0x03e
59
60#define DC_CMD_STATE_ACCESS 0x040
61#define READ_MUX (1 << 0)
62#define WRITE_MUX (1 << 2)
63
64#define DC_CMD_STATE_CONTROL 0x041
65#define GENERAL_ACT_REQ (1 << 0)
66#define WIN_A_ACT_REQ (1 << 1)
67#define WIN_B_ACT_REQ (1 << 2)
68#define WIN_C_ACT_REQ (1 << 3)
69#define GENERAL_UPDATE (1 << 8)
70#define WIN_A_UPDATE (1 << 9)
71#define WIN_B_UPDATE (1 << 10)
72#define WIN_C_UPDATE (1 << 11)
73#define NC_HOST_TRIG (1 << 24)
74
75#define DC_CMD_DISPLAY_WINDOW_HEADER 0x042
76#define WINDOW_A_SELECT (1 << 4)
77#define WINDOW_B_SELECT (1 << 5)
78#define WINDOW_C_SELECT (1 << 6)
79
80#define DC_CMD_REG_ACT_CONTROL 0x043
81
82#define DC_COM_CRC_CONTROL 0x300
83#define DC_COM_CRC_CHECKSUM 0x301
84#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
85#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
86#define LVS_OUTPUT_POLARITY_LOW (1 << 28)
87#define LHS_OUTPUT_POLARITY_LOW (1 << 30)
88#define DC_COM_PIN_OUTPUT_DATA(x) (0x30a + (x))
89#define DC_COM_PIN_INPUT_ENABLE(x) (0x30e + (x))
90#define DC_COM_PIN_INPUT_DATA(x) (0x312 + (x))
91#define DC_COM_PIN_OUTPUT_SELECT(x) (0x314 + (x))
92
93#define DC_COM_PIN_MISC_CONTROL 0x31b
94#define DC_COM_PIN_PM0_CONTROL 0x31c
95#define DC_COM_PIN_PM0_DUTY_CYCLE 0x31d
96#define DC_COM_PIN_PM1_CONTROL 0x31e
97#define DC_COM_PIN_PM1_DUTY_CYCLE 0x31f
98
99#define DC_COM_SPI_CONTROL 0x320
100#define DC_COM_SPI_START_BYTE 0x321
101#define DC_COM_HSPI_WRITE_DATA_AB 0x322
102#define DC_COM_HSPI_WRITE_DATA_CD 0x323
103#define DC_COM_HSPI_CS_DC 0x324
104#define DC_COM_SCRATCH_REGISTER_A 0x325
105#define DC_COM_SCRATCH_REGISTER_B 0x326
106#define DC_COM_GPIO_CTRL 0x327
107#define DC_COM_GPIO_DEBOUNCE_COUNTER 0x328
108#define DC_COM_CRC_CHECKSUM_LATCHED 0x329
109
110#define DC_DISP_DISP_SIGNAL_OPTIONS0 0x400
111#define H_PULSE_0_ENABLE (1 << 8)
112#define H_PULSE_1_ENABLE (1 << 10)
113#define H_PULSE_2_ENABLE (1 << 12)
114
115#define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401
116
117#define DC_DISP_DISP_WIN_OPTIONS 0x402
118#define HDMI_ENABLE (1 << 30)
119
120#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
121#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
122#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16)
123#define WINDOW_B_THRESHOLD(x) (((x) & 0x7f) << 8)
124#define WINDOW_C_THRESHOLD(x) (((x) & 0xff) << 0)
125
126#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
127#define CURSOR_DELAY(x) (((x) & 0x3f) << 24)
128#define WINDOW_A_DELAY(x) (((x) & 0x3f) << 16)
129#define WINDOW_B_DELAY(x) (((x) & 0x3f) << 8)
130#define WINDOW_C_DELAY(x) (((x) & 0x3f) << 0)
131
132#define DC_DISP_DISP_TIMING_OPTIONS 0x405
133#define VSYNC_H_POSITION(x) ((x) & 0xfff)
134
135#define DC_DISP_REF_TO_SYNC 0x406
136#define DC_DISP_SYNC_WIDTH 0x407
137#define DC_DISP_BACK_PORCH 0x408
138#define DC_DISP_ACTIVE 0x409
139#define DC_DISP_FRONT_PORCH 0x40a
140#define DC_DISP_H_PULSE0_CONTROL 0x40b
141#define DC_DISP_H_PULSE0_POSITION_A 0x40c
142#define DC_DISP_H_PULSE0_POSITION_B 0x40d
143#define DC_DISP_H_PULSE0_POSITION_C 0x40e
144#define DC_DISP_H_PULSE0_POSITION_D 0x40f
145#define DC_DISP_H_PULSE1_CONTROL 0x410
146#define DC_DISP_H_PULSE1_POSITION_A 0x411
147#define DC_DISP_H_PULSE1_POSITION_B 0x412
148#define DC_DISP_H_PULSE1_POSITION_C 0x413
149#define DC_DISP_H_PULSE1_POSITION_D 0x414
150#define DC_DISP_H_PULSE2_CONTROL 0x415
151#define DC_DISP_H_PULSE2_POSITION_A 0x416
152#define DC_DISP_H_PULSE2_POSITION_B 0x417
153#define DC_DISP_H_PULSE2_POSITION_C 0x418
154#define DC_DISP_H_PULSE2_POSITION_D 0x419
155#define DC_DISP_V_PULSE0_CONTROL 0x41a
156#define DC_DISP_V_PULSE0_POSITION_A 0x41b
157#define DC_DISP_V_PULSE0_POSITION_B 0x41c
158#define DC_DISP_V_PULSE0_POSITION_C 0x41d
159#define DC_DISP_V_PULSE1_CONTROL 0x41e
160#define DC_DISP_V_PULSE1_POSITION_A 0x41f
161#define DC_DISP_V_PULSE1_POSITION_B 0x420
162#define DC_DISP_V_PULSE1_POSITION_C 0x421
163#define DC_DISP_V_PULSE2_CONTROL 0x422
164#define DC_DISP_V_PULSE2_POSITION_A 0x423
165#define DC_DISP_V_PULSE3_CONTROL 0x424
166#define DC_DISP_V_PULSE3_POSITION_A 0x425
167#define DC_DISP_M0_CONTROL 0x426
168#define DC_DISP_M1_CONTROL 0x427
169#define DC_DISP_DI_CONTROL 0x428
170#define DC_DISP_PP_CONTROL 0x429
171#define DC_DISP_PP_SELECT_A 0x42a
172#define DC_DISP_PP_SELECT_B 0x42b
173#define DC_DISP_PP_SELECT_C 0x42c
174#define DC_DISP_PP_SELECT_D 0x42d
175
176#define PULSE_MODE_NORMAL (0 << 3)
177#define PULSE_MODE_ONE_CLOCK (1 << 3)
178#define PULSE_POLARITY_HIGH (0 << 4)
179#define PULSE_POLARITY_LOW (1 << 4)
180#define PULSE_QUAL_ALWAYS (0 << 6)
181#define PULSE_QUAL_VACTIVE (2 << 6)
182#define PULSE_QUAL_VACTIVE1 (3 << 6)
183#define PULSE_LAST_START_A (0 << 8)
184#define PULSE_LAST_END_A (1 << 8)
185#define PULSE_LAST_START_B (2 << 8)
186#define PULSE_LAST_END_B (3 << 8)
187#define PULSE_LAST_START_C (4 << 8)
188#define PULSE_LAST_END_C (5 << 8)
189#define PULSE_LAST_START_D (6 << 8)
190#define PULSE_LAST_END_D (7 << 8)
191
192#define PULSE_START(x) (((x) & 0xfff) << 0)
193#define PULSE_END(x) (((x) & 0xfff) << 16)
194
195#define DC_DISP_DISP_CLOCK_CONTROL 0x42e
196#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
197#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
198#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
199#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
200#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
201#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
202#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
203#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
204#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
205#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
206#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
207#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
208#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
209#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
210
211#define DC_DISP_DISP_INTERFACE_CONTROL 0x42f
212#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
213#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
214#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
215#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
216#define DISP_DATA_FORMAT_DF2S (4 << 0)
217#define DISP_DATA_FORMAT_DF3S (5 << 0)
218#define DISP_DATA_FORMAT_DFSPI (6 << 0)
219#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
220#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
221#define DISP_ALIGNMENT_MSB (0 << 8)
222#define DISP_ALIGNMENT_LSB (1 << 8)
223#define DISP_ORDER_RED_BLUE (0 << 9)
224#define DISP_ORDER_BLUE_RED (1 << 9)
225
226#define DC_DISP_DISP_COLOR_CONTROL 0x430
227#define BASE_COLOR_SIZE666 (0 << 0)
228#define BASE_COLOR_SIZE111 (1 << 0)
229#define BASE_COLOR_SIZE222 (2 << 0)
230#define BASE_COLOR_SIZE333 (3 << 0)
231#define BASE_COLOR_SIZE444 (4 << 0)
232#define BASE_COLOR_SIZE555 (5 << 0)
233#define BASE_COLOR_SIZE565 (6 << 0)
234#define BASE_COLOR_SIZE332 (7 << 0)
235#define BASE_COLOR_SIZE888 (8 << 0)
236#define DITHER_CONTROL_DISABLE (0 << 8)
237#define DITHER_CONTROL_ORDERED (2 << 8)
238#define DITHER_CONTROL_ERRDIFF (3 << 8)
239
240#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
241
242#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
243#define DE_SELECT_ACTIVE_BLANK (0 << 0)
244#define DE_SELECT_ACTIVE (1 << 0)
245#define DE_SELECT_ACTIVE_IS (2 << 0)
246#define DE_CONTROL_ONECLK (0 << 2)
247#define DE_CONTROL_NORMAL (1 << 2)
248#define DE_CONTROL_EARLY_EXT (2 << 2)
249#define DE_CONTROL_EARLY (3 << 2)
250#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
251
252#define DC_DISP_SERIAL_INTERFACE_OPTIONS 0x433
253#define DC_DISP_LCD_SPI_OPTIONS 0x434
254#define DC_DISP_BORDER_COLOR 0x435
255#define DC_DISP_COLOR_KEY0_LOWER 0x436
256#define DC_DISP_COLOR_KEY0_UPPER 0x437
257#define DC_DISP_COLOR_KEY1_LOWER 0x438
258#define DC_DISP_COLOR_KEY1_UPPER 0x439
259
260#define DC_DISP_CURSOR_FOREGROUND 0x43c
261#define DC_DISP_CURSOR_BACKGROUND 0x43d
262
263#define DC_DISP_CURSOR_START_ADDR 0x43e
264#define DC_DISP_CURSOR_START_ADDR_NS 0x43f
265
266#define DC_DISP_CURSOR_POSITION 0x440
267#define DC_DISP_CURSOR_POSITION_NS 0x441
268
269#define DC_DISP_INIT_SEQ_CONTROL 0x442
270#define DC_DISP_SPI_INIT_SEQ_DATA_A 0x443
271#define DC_DISP_SPI_INIT_SEQ_DATA_B 0x444
272#define DC_DISP_SPI_INIT_SEQ_DATA_C 0x445
273#define DC_DISP_SPI_INIT_SEQ_DATA_D 0x446
274
275#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
276#define DC_DISP_MCCIF_DISPLAY0A_HYST 0x481
277#define DC_DISP_MCCIF_DISPLAY0B_HYST 0x482
278#define DC_DISP_MCCIF_DISPLAY1A_HYST 0x483
279#define DC_DISP_MCCIF_DISPLAY1B_HYST 0x484
280
281#define DC_DISP_DAC_CRT_CTRL 0x4c0
282#define DC_DISP_DISP_MISC_CONTROL 0x4c1
283#define DC_DISP_SD_CONTROL 0x4c2
284#define DC_DISP_SD_CSC_COEFF 0x4c3
285#define DC_DISP_SD_LUT(x) (0x4c4 + (x))
286#define DC_DISP_SD_FLICKER_CONTROL 0x4cd
287#define DC_DISP_DC_PIXEL_COUNT 0x4ce
288#define DC_DISP_SD_HISTOGRAM(x) (0x4cf + (x))
289#define DC_DISP_SD_BL_PARAMETERS 0x4d7
290#define DC_DISP_SD_BL_TF(x) (0x4d8 + (x))
291#define DC_DISP_SD_BL_CONTROL 0x4dc
292#define DC_DISP_SD_HW_K_VALUES 0x4dd
293#define DC_DISP_SD_MAN_K_VALUES 0x4de
294
295#define DC_WIN_CSC_YOF 0x611
296#define DC_WIN_CSC_KYRGB 0x612
297#define DC_WIN_CSC_KUR 0x613
298#define DC_WIN_CSC_KVR 0x614
299#define DC_WIN_CSC_KUG 0x615
300#define DC_WIN_CSC_KVG 0x616
301#define DC_WIN_CSC_KUB 0x617
302#define DC_WIN_CSC_KVB 0x618
303
304#define DC_WIN_WIN_OPTIONS 0x700
305#define COLOR_EXPAND (1 << 6)
306#define CSC_ENABLE (1 << 18)
307#define WIN_ENABLE (1 << 30)
308
309#define DC_WIN_BYTE_SWAP 0x701
310#define BYTE_SWAP_NOSWAP (0 << 0)
311#define BYTE_SWAP_SWAP2 (1 << 0)
312#define BYTE_SWAP_SWAP4 (2 << 0)
313#define BYTE_SWAP_SWAP4HW (3 << 0)
314
315#define DC_WIN_BUFFER_CONTROL 0x702
316#define BUFFER_CONTROL_HOST (0 << 0)
317#define BUFFER_CONTROL_VI (1 << 0)
318#define BUFFER_CONTROL_EPP (2 << 0)
319#define BUFFER_CONTROL_MPEGE (3 << 0)
320#define BUFFER_CONTROL_SB2D (4 << 0)
321
322#define DC_WIN_COLOR_DEPTH 0x703
323#define WIN_COLOR_DEPTH_P1 0
324#define WIN_COLOR_DEPTH_P2 1
325#define WIN_COLOR_DEPTH_P4 2
326#define WIN_COLOR_DEPTH_P8 3
327#define WIN_COLOR_DEPTH_B4G4R4A4 4
328#define WIN_COLOR_DEPTH_B5G5R5A 5
329#define WIN_COLOR_DEPTH_B5G6R5 6
330#define WIN_COLOR_DEPTH_AB5G5R5 7
331#define WIN_COLOR_DEPTH_B8G8R8A8 12
332#define WIN_COLOR_DEPTH_R8G8B8A8 13
333#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 14
334#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 15
335#define WIN_COLOR_DEPTH_YCbCr422 16
336#define WIN_COLOR_DEPTH_YUV422 17
337#define WIN_COLOR_DEPTH_YCbCr420P 18
338#define WIN_COLOR_DEPTH_YUV420P 19
339#define WIN_COLOR_DEPTH_YCbCr422P 20
340#define WIN_COLOR_DEPTH_YUV422P 21
341#define WIN_COLOR_DEPTH_YCbCr422R 22
342#define WIN_COLOR_DEPTH_YUV422R 23
343#define WIN_COLOR_DEPTH_YCbCr422RA 24
344#define WIN_COLOR_DEPTH_YUV422RA 25
345
346#define DC_WIN_POSITION 0x704
347#define H_POSITION(x) (((x) & 0x1fff) << 0)
348#define V_POSITION(x) (((x) & 0x1fff) << 16)
349
350#define DC_WIN_SIZE 0x705
351#define H_SIZE(x) (((x) & 0x1fff) << 0)
352#define V_SIZE(x) (((x) & 0x1fff) << 16)
353
354#define DC_WIN_PRESCALED_SIZE 0x706
355#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
356#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
357
358#define DC_WIN_H_INITIAL_DDA 0x707
359#define DC_WIN_V_INITIAL_DDA 0x708
360#define DC_WIN_DDA_INC 0x709
361#define H_DDA_INC(x) (((x) & 0xffff) << 0)
362#define V_DDA_INC(x) (((x) & 0xffff) << 16)
363
364#define DC_WIN_LINE_STRIDE 0x70a
365#define DC_WIN_BUF_STRIDE 0x70b
366#define DC_WIN_UV_BUF_STRIDE 0x70c
367#define DC_WIN_BUFFER_ADDR_MODE 0x70d
368#define DC_WIN_DV_CONTROL 0x70e
369
370#define DC_WIN_BLEND_NOKEY 0x70f
371#define DC_WIN_BLEND_1WIN 0x710
372#define DC_WIN_BLEND_2WIN_X 0x711
373#define DC_WIN_BLEND_2WIN_Y 0x712
374#define DC_WIN_BLEND_3WIN_XY 0x713
375
376#define DC_WIN_HP_FETCH_CONTROL 0x714
377
378#define DC_WINBUF_START_ADDR 0x800
379#define DC_WINBUF_START_ADDR_NS 0x801
380#define DC_WINBUF_START_ADDR_U 0x802
381#define DC_WINBUF_START_ADDR_U_NS 0x803
382#define DC_WINBUF_START_ADDR_V 0x804
383#define DC_WINBUF_START_ADDR_V_NS 0x805
384
385#define DC_WINBUF_ADDR_H_OFFSET 0x806
386#define DC_WINBUF_ADDR_H_OFFSET_NS 0x807
387#define DC_WINBUF_ADDR_V_OFFSET 0x808
388#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809
389
390#define DC_WINBUF_UFLOW_STATUS 0x80a
391
392#define DC_WINBUF_AD_UFLOW_STATUS 0xbca
393#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
394#define DC_WINBUF_CD_UFLOW_STATUS 0xfca
395
396/* synchronization points */
397#define SYNCPT_VBLANK0 26
398#define SYNCPT_VBLANK1 27
399
400#endif /* TEGRA_DC_H */
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
new file mode 100644
index 000000000000..9d452df5bcad
--- /dev/null
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -0,0 +1,217 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/of_address.h>
12#include <linux/of_platform.h>
13
14#include <linux/dma-mapping.h>
15#include <asm/dma-iommu.h>
16
17#include "drm.h"
18
19#define DRIVER_NAME "tegra"
20#define DRIVER_DESC "NVIDIA Tegra graphics"
21#define DRIVER_DATE "20120330"
22#define DRIVER_MAJOR 0
23#define DRIVER_MINOR 0
24#define DRIVER_PATCHLEVEL 0
25
26static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
27{
28 struct device *dev = drm->dev;
29 struct host1x *host1x;
30 int err;
31
32 host1x = dev_get_drvdata(dev);
33 drm->dev_private = host1x;
34 host1x->drm = drm;
35
36 drm_mode_config_init(drm);
37
38 err = host1x_drm_init(host1x, drm);
39 if (err < 0)
40 return err;
41
42 err = drm_vblank_init(drm, drm->mode_config.num_crtc);
43 if (err < 0)
44 return err;
45
46 err = tegra_drm_fb_init(drm);
47 if (err < 0)
48 return err;
49
50 drm_kms_helper_poll_init(drm);
51
52 return 0;
53}
54
55static int tegra_drm_unload(struct drm_device *drm)
56{
57 drm_kms_helper_poll_fini(drm);
58 tegra_drm_fb_exit(drm);
59
60 drm_mode_config_cleanup(drm);
61
62 return 0;
63}
64
65static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
66{
67 return 0;
68}
69
70static void tegra_drm_lastclose(struct drm_device *drm)
71{
72 struct host1x *host1x = drm->dev_private;
73
74 drm_fbdev_cma_restore_mode(host1x->fbdev);
75}
76
77static struct drm_ioctl_desc tegra_drm_ioctls[] = {
78};
79
80static const struct file_operations tegra_drm_fops = {
81 .owner = THIS_MODULE,
82 .open = drm_open,
83 .release = drm_release,
84 .unlocked_ioctl = drm_ioctl,
85 .mmap = drm_gem_cma_mmap,
86 .poll = drm_poll,
87 .fasync = drm_fasync,
88 .read = drm_read,
89#ifdef CONFIG_COMPAT
90 .compat_ioctl = drm_compat_ioctl,
91#endif
92 .llseek = noop_llseek,
93};
94
95static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe)
96{
97 struct drm_crtc *crtc;
98
99 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) {
100 struct tegra_dc *dc = to_tegra_dc(crtc);
101
102 if (dc->pipe == pipe)
103 return crtc;
104 }
105
106 return NULL;
107}
108
109static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc)
110{
111 /* TODO: implement real hardware counter using syncpoints */
112 return drm_vblank_count(dev, crtc);
113}
114
115static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
116{
117 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
118 struct tegra_dc *dc = to_tegra_dc(crtc);
119
120 if (!crtc)
121 return -ENODEV;
122
123 tegra_dc_enable_vblank(dc);
124
125 return 0;
126}
127
128static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
129{
130 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
131 struct tegra_dc *dc = to_tegra_dc(crtc);
132
133 if (crtc)
134 tegra_dc_disable_vblank(dc);
135}
136
137static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
138{
139 struct drm_crtc *crtc;
140
141 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
142 tegra_dc_cancel_page_flip(crtc, file);
143}
144
145#ifdef CONFIG_DEBUG_FS
146static int tegra_debugfs_framebuffers(struct seq_file *s, void *data)
147{
148 struct drm_info_node *node = (struct drm_info_node *)s->private;
149 struct drm_device *drm = node->minor->dev;
150 struct drm_framebuffer *fb;
151
152 mutex_lock(&drm->mode_config.fb_lock);
153
154 list_for_each_entry(fb, &drm->mode_config.fb_list, head) {
155 seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
156 fb->base.id, fb->width, fb->height, fb->depth,
157 fb->bits_per_pixel,
158 atomic_read(&fb->refcount.refcount));
159 }
160
161 mutex_unlock(&drm->mode_config.fb_lock);
162
163 return 0;
164}
165
166static struct drm_info_list tegra_debugfs_list[] = {
167 { "framebuffers", tegra_debugfs_framebuffers, 0 },
168};
169
170static int tegra_debugfs_init(struct drm_minor *minor)
171{
172 return drm_debugfs_create_files(tegra_debugfs_list,
173 ARRAY_SIZE(tegra_debugfs_list),
174 minor->debugfs_root, minor);
175}
176
177static void tegra_debugfs_cleanup(struct drm_minor *minor)
178{
179 drm_debugfs_remove_files(tegra_debugfs_list,
180 ARRAY_SIZE(tegra_debugfs_list), minor);
181}
182#endif
183
184struct drm_driver tegra_drm_driver = {
185 .driver_features = DRIVER_BUS_PLATFORM | DRIVER_MODESET | DRIVER_GEM,
186 .load = tegra_drm_load,
187 .unload = tegra_drm_unload,
188 .open = tegra_drm_open,
189 .preclose = tegra_drm_preclose,
190 .lastclose = tegra_drm_lastclose,
191
192 .get_vblank_counter = tegra_drm_get_vblank_counter,
193 .enable_vblank = tegra_drm_enable_vblank,
194 .disable_vblank = tegra_drm_disable_vblank,
195
196#if defined(CONFIG_DEBUG_FS)
197 .debugfs_init = tegra_debugfs_init,
198 .debugfs_cleanup = tegra_debugfs_cleanup,
199#endif
200
201 .gem_free_object = drm_gem_cma_free_object,
202 .gem_vm_ops = &drm_gem_cma_vm_ops,
203 .dumb_create = drm_gem_cma_dumb_create,
204 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
205 .dumb_destroy = drm_gem_cma_dumb_destroy,
206
207 .ioctls = tegra_drm_ioctls,
208 .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
209 .fops = &tegra_drm_fops,
210
211 .name = DRIVER_NAME,
212 .desc = DRIVER_DESC,
213 .date = DRIVER_DATE,
214 .major = DRIVER_MAJOR,
215 .minor = DRIVER_MINOR,
216 .patchlevel = DRIVER_PATCHLEVEL,
217};
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
new file mode 100644
index 000000000000..a6c011da2ce9
--- /dev/null
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -0,0 +1,237 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#ifndef HOST1X_DRM_H
11#define HOST1X_DRM_H 1
12
13#include <drm/drmP.h>
14#include <drm/drm_crtc_helper.h>
15#include <drm/drm_edid.h>
16#include <drm/drm_fb_helper.h>
17#include <drm/drm_gem_cma_helper.h>
18#include <drm/drm_fb_cma_helper.h>
19#include <drm/drm_fixed.h>
20
21struct host1x {
22 struct drm_device *drm;
23 struct device *dev;
24 void __iomem *regs;
25 struct clk *clk;
26 int syncpt;
27 int irq;
28
29 struct mutex drm_clients_lock;
30 struct list_head drm_clients;
31 struct list_head drm_active;
32
33 struct mutex clients_lock;
34 struct list_head clients;
35
36 struct drm_fbdev_cma *fbdev;
37};
38
39struct host1x_client;
40
41struct host1x_client_ops {
42 int (*drm_init)(struct host1x_client *client, struct drm_device *drm);
43 int (*drm_exit)(struct host1x_client *client);
44};
45
46struct host1x_client {
47 struct host1x *host1x;
48 struct device *dev;
49
50 const struct host1x_client_ops *ops;
51
52 struct list_head list;
53};
54
55extern int host1x_drm_init(struct host1x *host1x, struct drm_device *drm);
56extern int host1x_drm_exit(struct host1x *host1x);
57
58extern int host1x_register_client(struct host1x *host1x,
59 struct host1x_client *client);
60extern int host1x_unregister_client(struct host1x *host1x,
61 struct host1x_client *client);
62
63struct tegra_output;
64
65struct tegra_dc {
66 struct host1x_client client;
67 spinlock_t lock;
68
69 struct host1x *host1x;
70 struct device *dev;
71
72 struct drm_crtc base;
73 int pipe;
74
75 struct clk *clk;
76
77 void __iomem *regs;
78 int irq;
79
80 struct tegra_output *rgb;
81
82 struct list_head list;
83
84 struct drm_info_list *debugfs_files;
85 struct drm_minor *minor;
86 struct dentry *debugfs;
87
88 /* page-flip handling */
89 struct drm_pending_vblank_event *event;
90};
91
92static inline struct tegra_dc *host1x_client_to_dc(struct host1x_client *client)
93{
94 return container_of(client, struct tegra_dc, client);
95}
96
97static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
98{
99 return container_of(crtc, struct tegra_dc, base);
100}
101
102static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
103 unsigned long reg)
104{
105 writel(value, dc->regs + (reg << 2));
106}
107
108static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
109 unsigned long reg)
110{
111 return readl(dc->regs + (reg << 2));
112}
113
114struct tegra_dc_window {
115 struct {
116 unsigned int x;
117 unsigned int y;
118 unsigned int w;
119 unsigned int h;
120 } src;
121 struct {
122 unsigned int x;
123 unsigned int y;
124 unsigned int w;
125 unsigned int h;
126 } dst;
127 unsigned int bits_per_pixel;
128 unsigned int format;
129 unsigned int stride[2];
130 unsigned long base[3];
131};
132
133/* from dc.c */
134extern unsigned int tegra_dc_format(uint32_t format);
135extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
136 const struct tegra_dc_window *window);
137extern void tegra_dc_enable_vblank(struct tegra_dc *dc);
138extern void tegra_dc_disable_vblank(struct tegra_dc *dc);
139extern void tegra_dc_cancel_page_flip(struct drm_crtc *crtc,
140 struct drm_file *file);
141
142struct tegra_output_ops {
143 int (*enable)(struct tegra_output *output);
144 int (*disable)(struct tegra_output *output);
145 int (*setup_clock)(struct tegra_output *output, struct clk *clk,
146 unsigned long pclk);
147 int (*check_mode)(struct tegra_output *output,
148 struct drm_display_mode *mode,
149 enum drm_mode_status *status);
150};
151
152enum tegra_output_type {
153 TEGRA_OUTPUT_RGB,
154 TEGRA_OUTPUT_HDMI,
155};
156
157struct tegra_output {
158 struct device_node *of_node;
159 struct device *dev;
160
161 const struct tegra_output_ops *ops;
162 enum tegra_output_type type;
163
164 struct i2c_adapter *ddc;
165 const struct edid *edid;
166 unsigned int hpd_irq;
167 int hpd_gpio;
168
169 struct drm_encoder encoder;
170 struct drm_connector connector;
171};
172
173static inline struct tegra_output *encoder_to_output(struct drm_encoder *e)
174{
175 return container_of(e, struct tegra_output, encoder);
176}
177
178static inline struct tegra_output *connector_to_output(struct drm_connector *c)
179{
180 return container_of(c, struct tegra_output, connector);
181}
182
183static inline int tegra_output_enable(struct tegra_output *output)
184{
185 if (output && output->ops && output->ops->enable)
186 return output->ops->enable(output);
187
188 return output ? -ENOSYS : -EINVAL;
189}
190
191static inline int tegra_output_disable(struct tegra_output *output)
192{
193 if (output && output->ops && output->ops->disable)
194 return output->ops->disable(output);
195
196 return output ? -ENOSYS : -EINVAL;
197}
198
199static inline int tegra_output_setup_clock(struct tegra_output *output,
200 struct clk *clk, unsigned long pclk)
201{
202 if (output && output->ops && output->ops->setup_clock)
203 return output->ops->setup_clock(output, clk, pclk);
204
205 return output ? -ENOSYS : -EINVAL;
206}
207
208static inline int tegra_output_check_mode(struct tegra_output *output,
209 struct drm_display_mode *mode,
210 enum drm_mode_status *status)
211{
212 if (output && output->ops && output->ops->check_mode)
213 return output->ops->check_mode(output, mode, status);
214
215 return output ? -ENOSYS : -EINVAL;
216}
217
218/* from rgb.c */
219extern int tegra_dc_rgb_probe(struct tegra_dc *dc);
220extern int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc);
221extern int tegra_dc_rgb_exit(struct tegra_dc *dc);
222
223/* from output.c */
224extern int tegra_output_parse_dt(struct tegra_output *output);
225extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
226extern int tegra_output_exit(struct tegra_output *output);
227
228/* from fb.c */
229extern int tegra_drm_fb_init(struct drm_device *drm);
230extern void tegra_drm_fb_exit(struct drm_device *drm);
231
232extern struct platform_driver tegra_host1x_driver;
233extern struct platform_driver tegra_hdmi_driver;
234extern struct platform_driver tegra_dc_driver;
235extern struct drm_driver tegra_drm_driver;
236
237#endif /* HOST1X_DRM_H */
diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c
new file mode 100644
index 000000000000..03914953cb1c
--- /dev/null
+++ b/drivers/gpu/host1x/drm/fb.c
@@ -0,0 +1,52 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include "drm.h"
11
12static void tegra_drm_fb_output_poll_changed(struct drm_device *drm)
13{
14 struct host1x *host1x = drm->dev_private;
15
16 drm_fbdev_cma_hotplug_event(host1x->fbdev);
17}
18
19static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
20 .fb_create = drm_fb_cma_create,
21 .output_poll_changed = tegra_drm_fb_output_poll_changed,
22};
23
24int tegra_drm_fb_init(struct drm_device *drm)
25{
26 struct host1x *host1x = drm->dev_private;
27 struct drm_fbdev_cma *fbdev;
28
29 drm->mode_config.min_width = 0;
30 drm->mode_config.min_height = 0;
31
32 drm->mode_config.max_width = 4096;
33 drm->mode_config.max_height = 4096;
34
35 drm->mode_config.funcs = &tegra_drm_mode_funcs;
36
37 fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc,
38 drm->mode_config.num_connector);
39 if (IS_ERR(fbdev))
40 return PTR_ERR(fbdev);
41
42 host1x->fbdev = fbdev;
43
44 return 0;
45}
46
47void tegra_drm_fb_exit(struct drm_device *drm)
48{
49 struct host1x *host1x = drm->dev_private;
50
51 drm_fbdev_cma_fini(host1x->fbdev);
52}
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
new file mode 100644
index 000000000000..bb747f6cd1a4
--- /dev/null
+++ b/drivers/gpu/host1x/drm/hdmi.c
@@ -0,0 +1,1312 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/clk.h>
11#include <linux/debugfs.h>
12#include <linux/gpio.h>
13#include <linux/hdmi.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17#include <linux/regulator/consumer.h>
18#include <linux/clk/tegra.h>
19
20#include <drm/drm_edid.h>
21
22#include "hdmi.h"
23#include "drm.h"
24#include "dc.h"
25
26struct tegra_hdmi {
27 struct host1x_client client;
28 struct tegra_output output;
29 struct device *dev;
30
31 struct regulator *vdd;
32 struct regulator *pll;
33
34 void __iomem *regs;
35 unsigned int irq;
36
37 struct clk *clk_parent;
38 struct clk *clk;
39
40 unsigned int audio_source;
41 unsigned int audio_freq;
42 bool stereo;
43 bool dvi;
44
45 struct drm_info_list *debugfs_files;
46 struct drm_minor *minor;
47 struct dentry *debugfs;
48};
49
50static inline struct tegra_hdmi *
51host1x_client_to_hdmi(struct host1x_client *client)
52{
53 return container_of(client, struct tegra_hdmi, client);
54}
55
56static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
57{
58 return container_of(output, struct tegra_hdmi, output);
59}
60
61#define HDMI_AUDIOCLK_FREQ 216000000
62#define HDMI_REKEY_DEFAULT 56
63
64enum {
65 AUTO = 0,
66 SPDIF,
67 HDA,
68};
69
70static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi,
71 unsigned long reg)
72{
73 return readl(hdmi->regs + (reg << 2));
74}
75
76static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val,
77 unsigned long reg)
78{
79 writel(val, hdmi->regs + (reg << 2));
80}
81
82struct tegra_hdmi_audio_config {
83 unsigned int pclk;
84 unsigned int n;
85 unsigned int cts;
86 unsigned int aval;
87};
88
89static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
90 { 25200000, 4096, 25200, 24000 },
91 { 27000000, 4096, 27000, 24000 },
92 { 74250000, 4096, 74250, 24000 },
93 { 148500000, 4096, 148500, 24000 },
94 { 0, 0, 0, 0 },
95};
96
97static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
98 { 25200000, 5880, 26250, 25000 },
99 { 27000000, 5880, 28125, 25000 },
100 { 74250000, 4704, 61875, 20000 },
101 { 148500000, 4704, 123750, 20000 },
102 { 0, 0, 0, 0 },
103};
104
105static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
106 { 25200000, 6144, 25200, 24000 },
107 { 27000000, 6144, 27000, 24000 },
108 { 74250000, 6144, 74250, 24000 },
109 { 148500000, 6144, 148500, 24000 },
110 { 0, 0, 0, 0 },
111};
112
113static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
114 { 25200000, 11760, 26250, 25000 },
115 { 27000000, 11760, 28125, 25000 },
116 { 74250000, 9408, 61875, 20000 },
117 { 148500000, 9408, 123750, 20000 },
118 { 0, 0, 0, 0 },
119};
120
121static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
122 { 25200000, 12288, 25200, 24000 },
123 { 27000000, 12288, 27000, 24000 },
124 { 74250000, 12288, 74250, 24000 },
125 { 148500000, 12288, 148500, 24000 },
126 { 0, 0, 0, 0 },
127};
128
129static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
130 { 25200000, 23520, 26250, 25000 },
131 { 27000000, 23520, 28125, 25000 },
132 { 74250000, 18816, 61875, 20000 },
133 { 148500000, 18816, 123750, 20000 },
134 { 0, 0, 0, 0 },
135};
136
137static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
138 { 25200000, 24576, 25200, 24000 },
139 { 27000000, 24576, 27000, 24000 },
140 { 74250000, 24576, 74250, 24000 },
141 { 148500000, 24576, 148500, 24000 },
142 { 0, 0, 0, 0 },
143};
144
145struct tmds_config {
146 unsigned int pclk;
147 u32 pll0;
148 u32 pll1;
149 u32 pe_current;
150 u32 drive_current;
151};
152
153static const struct tmds_config tegra2_tmds_config[] = {
154 { /* slow pixel clock modes */
155 .pclk = 27000000,
156 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
157 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
158 SOR_PLL_TX_REG_LOAD(3),
159 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
160 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
161 PE_CURRENT1(PE_CURRENT_0_0_mA) |
162 PE_CURRENT2(PE_CURRENT_0_0_mA) |
163 PE_CURRENT3(PE_CURRENT_0_0_mA),
164 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
165 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
166 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
167 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
168 },
169 { /* high pixel clock modes */
170 .pclk = UINT_MAX,
171 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
172 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
173 SOR_PLL_TX_REG_LOAD(3),
174 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
175 .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
176 PE_CURRENT1(PE_CURRENT_6_0_mA) |
177 PE_CURRENT2(PE_CURRENT_6_0_mA) |
178 PE_CURRENT3(PE_CURRENT_6_0_mA),
179 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
180 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
181 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
182 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
183 },
184};
185
186static const struct tmds_config tegra3_tmds_config[] = {
187 { /* 480p modes */
188 .pclk = 27000000,
189 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
190 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
191 SOR_PLL_TX_REG_LOAD(0),
192 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
193 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
194 PE_CURRENT1(PE_CURRENT_0_0_mA) |
195 PE_CURRENT2(PE_CURRENT_0_0_mA) |
196 PE_CURRENT3(PE_CURRENT_0_0_mA),
197 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
198 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
199 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
200 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
201 }, { /* 720p modes */
202 .pclk = 74250000,
203 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
204 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
205 SOR_PLL_TX_REG_LOAD(0),
206 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
207 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
208 PE_CURRENT1(PE_CURRENT_5_0_mA) |
209 PE_CURRENT2(PE_CURRENT_5_0_mA) |
210 PE_CURRENT3(PE_CURRENT_5_0_mA),
211 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
212 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
213 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
214 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
215 }, { /* 1080p modes */
216 .pclk = UINT_MAX,
217 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
218 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
219 SOR_PLL_TX_REG_LOAD(0),
220 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
221 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
222 PE_CURRENT1(PE_CURRENT_5_0_mA) |
223 PE_CURRENT2(PE_CURRENT_5_0_mA) |
224 PE_CURRENT3(PE_CURRENT_5_0_mA),
225 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
226 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
227 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
228 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
229 },
230};
231
232static const struct tegra_hdmi_audio_config *
233tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
234{
235 const struct tegra_hdmi_audio_config *table;
236
237 switch (audio_freq) {
238 case 32000:
239 table = tegra_hdmi_audio_32k;
240 break;
241
242 case 44100:
243 table = tegra_hdmi_audio_44_1k;
244 break;
245
246 case 48000:
247 table = tegra_hdmi_audio_48k;
248 break;
249
250 case 88200:
251 table = tegra_hdmi_audio_88_2k;
252 break;
253
254 case 96000:
255 table = tegra_hdmi_audio_96k;
256 break;
257
258 case 176400:
259 table = tegra_hdmi_audio_176_4k;
260 break;
261
262 case 192000:
263 table = tegra_hdmi_audio_192k;
264 break;
265
266 default:
267 return NULL;
268 }
269
270 while (table->pclk) {
271 if (table->pclk == pclk)
272 return table;
273
274 table++;
275 }
276
277 return NULL;
278}
279
280static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
281{
282 const unsigned int freqs[] = {
283 32000, 44100, 48000, 88200, 96000, 176400, 192000
284 };
285 unsigned int i;
286
287 for (i = 0; i < ARRAY_SIZE(freqs); i++) {
288 unsigned int f = freqs[i];
289 unsigned int eight_half;
290 unsigned long value;
291 unsigned int delta;
292
293 if (f > 96000)
294 delta = 2;
295 else if (f > 480000)
296 delta = 6;
297 else
298 delta = 9;
299
300 eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
301 value = AUDIO_FS_LOW(eight_half - delta) |
302 AUDIO_FS_HIGH(eight_half + delta);
303 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i));
304 }
305}
306
307static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
308{
309 struct device_node *node = hdmi->dev->of_node;
310 const struct tegra_hdmi_audio_config *config;
311 unsigned int offset = 0;
312 unsigned long value;
313
314 switch (hdmi->audio_source) {
315 case HDA:
316 value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
317 break;
318
319 case SPDIF:
320 value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
321 break;
322
323 default:
324 value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
325 break;
326 }
327
328 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
329 value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
330 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
331 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
332 } else {
333 value |= AUDIO_CNTRL0_INJECT_NULLSMPL;
334 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
335
336 value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
337 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
338 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
339 }
340
341 config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
342 if (!config) {
343 dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
344 hdmi->audio_freq, pclk);
345 return -EINVAL;
346 }
347
348 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
349
350 value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
351 AUDIO_N_VALUE(config->n - 1);
352 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
353
354 tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
355 HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
356
357 value = ACR_SUBPACK_CTS(config->cts);
358 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
359
360 value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
361 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE);
362
363 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N);
364 value &= ~AUDIO_N_RESETF;
365 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
366
367 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
368 switch (hdmi->audio_freq) {
369 case 32000:
370 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320;
371 break;
372
373 case 44100:
374 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441;
375 break;
376
377 case 48000:
378 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480;
379 break;
380
381 case 88200:
382 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882;
383 break;
384
385 case 96000:
386 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960;
387 break;
388
389 case 176400:
390 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764;
391 break;
392
393 case 192000:
394 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920;
395 break;
396 }
397
398 tegra_hdmi_writel(hdmi, config->aval, offset);
399 }
400
401 tegra_hdmi_setup_audio_fs_tables(hdmi);
402
403 return 0;
404}
405
406static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size)
407{
408 unsigned long value = 0;
409 size_t i;
410
411 for (i = size; i > 0; i--)
412 value = (value << 8) | ptr[i - 1];
413
414 return value;
415}
416
417static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data,
418 size_t size)
419{
420 const u8 *ptr = data;
421 unsigned long offset;
422 unsigned long value;
423 size_t i, j;
424
425 switch (ptr[0]) {
426 case HDMI_INFOFRAME_TYPE_AVI:
427 offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER;
428 break;
429
430 case HDMI_INFOFRAME_TYPE_AUDIO:
431 offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER;
432 break;
433
434 case HDMI_INFOFRAME_TYPE_VENDOR:
435 offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER;
436 break;
437
438 default:
439 dev_err(hdmi->dev, "unsupported infoframe type: %02x\n",
440 ptr[0]);
441 return;
442 }
443
444 value = INFOFRAME_HEADER_TYPE(ptr[0]) |
445 INFOFRAME_HEADER_VERSION(ptr[1]) |
446 INFOFRAME_HEADER_LEN(ptr[2]);
447 tegra_hdmi_writel(hdmi, value, offset);
448 offset++;
449
450 /*
451 * Each subpack contains 7 bytes, divided into:
452 * - subpack_low: bytes 0 - 3
453 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
454 */
455 for (i = 3, j = 0; i < size; i += 7, j += 8) {
456 size_t rem = size - i, num = min_t(size_t, rem, 4);
457
458 value = tegra_hdmi_subpack(&ptr[i], num);
459 tegra_hdmi_writel(hdmi, value, offset++);
460
461 num = min_t(size_t, rem - num, 3);
462
463 value = tegra_hdmi_subpack(&ptr[i + 4], num);
464 tegra_hdmi_writel(hdmi, value, offset++);
465 }
466}
467
468static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
469 struct drm_display_mode *mode)
470{
471 struct hdmi_avi_infoframe frame;
472 u8 buffer[17];
473 ssize_t err;
474
475 if (hdmi->dvi) {
476 tegra_hdmi_writel(hdmi, 0,
477 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
478 return;
479 }
480
481 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
482 if (err < 0) {
483 dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
484 return;
485 }
486
487 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
488 if (err < 0) {
489 dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err);
490 return;
491 }
492
493 tegra_hdmi_write_infopack(hdmi, buffer, err);
494
495 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
496 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
497}
498
499static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
500{
501 struct hdmi_audio_infoframe frame;
502 u8 buffer[14];
503 ssize_t err;
504
505 if (hdmi->dvi) {
506 tegra_hdmi_writel(hdmi, 0,
507 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
508 return;
509 }
510
511 err = hdmi_audio_infoframe_init(&frame);
512 if (err < 0) {
513 dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n",
514 err);
515 return;
516 }
517
518 frame.channels = 2;
519
520 err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
521 if (err < 0) {
522 dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n",
523 err);
524 return;
525 }
526
527 /*
528 * The audio infoframe has only one set of subpack registers, so the
529 * infoframe needs to be truncated. One set of subpack registers can
530 * contain 7 bytes. Including the 3 byte header only the first 10
531 * bytes can be programmed.
532 */
533 tegra_hdmi_write_infopack(hdmi, buffer, min(10, err));
534
535 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
536 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
537}
538
539static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
540{
541 struct hdmi_vendor_infoframe frame;
542 unsigned long value;
543 u8 buffer[10];
544 ssize_t err;
545
546 if (!hdmi->stereo) {
547 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
548 value &= ~GENERIC_CTRL_ENABLE;
549 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
550 return;
551 }
552
553 memset(&frame, 0, sizeof(frame));
554
555 frame.type = HDMI_INFOFRAME_TYPE_VENDOR;
556 frame.version = 0x01;
557 frame.length = 6;
558
559 frame.data[0] = 0x03; /* regid0 */
560 frame.data[1] = 0x0c; /* regid1 */
561 frame.data[2] = 0x00; /* regid2 */
562 frame.data[3] = 0x02 << 5; /* video format */
563
564 /* TODO: 74 MHz limit? */
565 if (1) {
566 frame.data[4] = 0x00 << 4; /* 3D structure */
567 } else {
568 frame.data[4] = 0x08 << 4; /* 3D structure */
569 frame.data[5] = 0x00 << 4; /* 3D ext. data */
570 }
571
572 err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
573 if (err < 0) {
574 dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n",
575 err);
576 return;
577 }
578
579 tegra_hdmi_write_infopack(hdmi, buffer, err);
580
581 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
582 value |= GENERIC_CTRL_ENABLE;
583 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
584}
585
586static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
587 const struct tmds_config *tmds)
588{
589 unsigned long value;
590
591 tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
592 tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
593 tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
594
595 value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
596 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
597}
598
599static int tegra_output_hdmi_enable(struct tegra_output *output)
600{
601 unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
602 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
603 struct drm_display_mode *mode = &dc->base.mode;
604 struct tegra_hdmi *hdmi = to_hdmi(output);
605 struct device_node *node = hdmi->dev->of_node;
606 unsigned int pulse_start, div82, pclk;
607 const struct tmds_config *tmds;
608 unsigned int num_tmds;
609 unsigned long value;
610 int retries = 1000;
611 int err;
612
613 pclk = mode->clock * 1000;
614 h_sync_width = mode->hsync_end - mode->hsync_start;
615 h_back_porch = mode->htotal - mode->hsync_end;
616 h_front_porch = mode->hsync_start - mode->hdisplay;
617
618 err = regulator_enable(hdmi->vdd);
619 if (err < 0) {
620 dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
621 return err;
622 }
623
624 err = regulator_enable(hdmi->pll);
625 if (err < 0) {
626 dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
627 return err;
628 }
629
630 /*
631 * This assumes that the display controller will divide its parent
632 * clock by 2 to generate the pixel clock.
633 */
634 err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2);
635 if (err < 0) {
636 dev_err(hdmi->dev, "failed to setup clock: %d\n", err);
637 return err;
638 }
639
640 err = clk_set_rate(hdmi->clk, pclk);
641 if (err < 0)
642 return err;
643
644 err = clk_enable(hdmi->clk);
645 if (err < 0) {
646 dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
647 return err;
648 }
649
650 tegra_periph_reset_assert(hdmi->clk);
651 usleep_range(1000, 2000);
652 tegra_periph_reset_deassert(hdmi->clk);
653
654 tegra_dc_writel(dc, VSYNC_H_POSITION(1),
655 DC_DISP_DISP_TIMING_OPTIONS);
656 tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
657 DC_DISP_DISP_COLOR_CONTROL);
658
659 /* video_preamble uses h_pulse2 */
660 pulse_start = 1 + h_sync_width + h_back_porch - 10;
661
662 tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
663
664 value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
665 PULSE_LAST_END_A;
666 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
667
668 value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
669 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
670
671 value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
672 VSYNC_WINDOW_ENABLE;
673 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
674
675 if (dc->pipe)
676 value = HDMI_SRC_DISPLAYB;
677 else
678 value = HDMI_SRC_DISPLAYA;
679
680 if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) ||
681 (mode->vdisplay == 576)))
682 tegra_hdmi_writel(hdmi,
683 value | ARM_VIDEO_RANGE_FULL,
684 HDMI_NV_PDISP_INPUT_CONTROL);
685 else
686 tegra_hdmi_writel(hdmi,
687 value | ARM_VIDEO_RANGE_LIMITED,
688 HDMI_NV_PDISP_INPUT_CONTROL);
689
690 div82 = clk_get_rate(hdmi->clk) / 1000000 * 4;
691 value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
692 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK);
693
694 if (!hdmi->dvi) {
695 err = tegra_hdmi_setup_audio(hdmi, pclk);
696 if (err < 0)
697 hdmi->dvi = true;
698 }
699
700 if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) {
701 /*
702 * TODO: add ELD support
703 */
704 }
705
706 rekey = HDMI_REKEY_DEFAULT;
707 value = HDMI_CTRL_REKEY(rekey);
708 value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch +
709 h_front_porch - rekey - 18) / 32);
710
711 if (!hdmi->dvi)
712 value |= HDMI_CTRL_ENABLE;
713
714 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL);
715
716 if (hdmi->dvi)
717 tegra_hdmi_writel(hdmi, 0x0,
718 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
719 else
720 tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
721 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
722
723 tegra_hdmi_setup_avi_infoframe(hdmi, mode);
724 tegra_hdmi_setup_audio_infoframe(hdmi);
725 tegra_hdmi_setup_stereo_infoframe(hdmi);
726
727 /* TMDS CONFIG */
728 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
729 num_tmds = ARRAY_SIZE(tegra3_tmds_config);
730 tmds = tegra3_tmds_config;
731 } else {
732 num_tmds = ARRAY_SIZE(tegra2_tmds_config);
733 tmds = tegra2_tmds_config;
734 }
735
736 for (i = 0; i < num_tmds; i++) {
737 if (pclk <= tmds[i].pclk) {
738 tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
739 break;
740 }
741 }
742
743 tegra_hdmi_writel(hdmi,
744 SOR_SEQ_CTL_PU_PC(0) |
745 SOR_SEQ_PU_PC_ALT(0) |
746 SOR_SEQ_PD_PC(8) |
747 SOR_SEQ_PD_PC_ALT(8),
748 HDMI_NV_PDISP_SOR_SEQ_CTL);
749
750 value = SOR_SEQ_INST_WAIT_TIME(1) |
751 SOR_SEQ_INST_WAIT_UNITS_VSYNC |
752 SOR_SEQ_INST_HALT |
753 SOR_SEQ_INST_PIN_A_LOW |
754 SOR_SEQ_INST_PIN_B_LOW |
755 SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
756
757 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0));
758 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8));
759
760 value = 0x1c800;
761 value &= ~SOR_CSTM_ROTCLK(~0);
762 value |= SOR_CSTM_ROTCLK(2);
763 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
764
765 tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
766 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
767 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
768
769 /* start SOR */
770 tegra_hdmi_writel(hdmi,
771 SOR_PWR_NORMAL_STATE_PU |
772 SOR_PWR_NORMAL_START_NORMAL |
773 SOR_PWR_SAFE_STATE_PD |
774 SOR_PWR_SETTING_NEW_TRIGGER,
775 HDMI_NV_PDISP_SOR_PWR);
776 tegra_hdmi_writel(hdmi,
777 SOR_PWR_NORMAL_STATE_PU |
778 SOR_PWR_NORMAL_START_NORMAL |
779 SOR_PWR_SAFE_STATE_PD |
780 SOR_PWR_SETTING_NEW_DONE,
781 HDMI_NV_PDISP_SOR_PWR);
782
783 do {
784 BUG_ON(--retries < 0);
785 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
786 } while (value & SOR_PWR_SETTING_NEW_PENDING);
787
788 value = SOR_STATE_ASY_CRCMODE_COMPLETE |
789 SOR_STATE_ASY_OWNER_HEAD0 |
790 SOR_STATE_ASY_SUBOWNER_BOTH |
791 SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
792 SOR_STATE_ASY_DEPOL_POS;
793
794 /* setup sync polarities */
795 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
796 value |= SOR_STATE_ASY_HSYNCPOL_POS;
797
798 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
799 value |= SOR_STATE_ASY_HSYNCPOL_NEG;
800
801 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
802 value |= SOR_STATE_ASY_VSYNCPOL_POS;
803
804 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
805 value |= SOR_STATE_ASY_VSYNCPOL_NEG;
806
807 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2);
808
809 value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
810 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1);
811
812 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
813 tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
814 tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED,
815 HDMI_NV_PDISP_SOR_STATE1);
816 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
817
818 tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
819
820 value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
821 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
822 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
823
824 value = DISP_CTRL_MODE_C_DISPLAY;
825 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
826
827 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
828 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
829
830 /* TODO: add HDCP support */
831
832 return 0;
833}
834
835static int tegra_output_hdmi_disable(struct tegra_output *output)
836{
837 struct tegra_hdmi *hdmi = to_hdmi(output);
838
839 tegra_periph_reset_assert(hdmi->clk);
840 clk_disable(hdmi->clk);
841 regulator_disable(hdmi->pll);
842 regulator_disable(hdmi->vdd);
843
844 return 0;
845}
846
847static int tegra_output_hdmi_setup_clock(struct tegra_output *output,
848 struct clk *clk, unsigned long pclk)
849{
850 struct tegra_hdmi *hdmi = to_hdmi(output);
851 struct clk *base;
852 int err;
853
854 err = clk_set_parent(clk, hdmi->clk_parent);
855 if (err < 0) {
856 dev_err(output->dev, "failed to set parent: %d\n", err);
857 return err;
858 }
859
860 base = clk_get_parent(hdmi->clk_parent);
861
862 /*
863 * This assumes that the parent clock is pll_d_out0 or pll_d2_out
864 * respectively, each of which divides the base pll_d by 2.
865 */
866 err = clk_set_rate(base, pclk * 2);
867 if (err < 0)
868 dev_err(output->dev,
869 "failed to set base clock rate to %lu Hz\n",
870 pclk * 2);
871
872 return 0;
873}
874
875static int tegra_output_hdmi_check_mode(struct tegra_output *output,
876 struct drm_display_mode *mode,
877 enum drm_mode_status *status)
878{
879 struct tegra_hdmi *hdmi = to_hdmi(output);
880 unsigned long pclk = mode->clock * 1000;
881 struct clk *parent;
882 long err;
883
884 parent = clk_get_parent(hdmi->clk_parent);
885
886 err = clk_round_rate(parent, pclk * 4);
887 if (err < 0)
888 *status = MODE_NOCLOCK;
889 else
890 *status = MODE_OK;
891
892 return 0;
893}
894
895static const struct tegra_output_ops hdmi_ops = {
896 .enable = tegra_output_hdmi_enable,
897 .disable = tegra_output_hdmi_disable,
898 .setup_clock = tegra_output_hdmi_setup_clock,
899 .check_mode = tegra_output_hdmi_check_mode,
900};
901
902static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
903{
904 struct drm_info_node *node = s->private;
905 struct tegra_hdmi *hdmi = node->info_ent->data;
906
907#define DUMP_REG(name) \
908 seq_printf(s, "%-56s %#05x %08lx\n", #name, name, \
909 tegra_hdmi_readl(hdmi, name))
910
911 DUMP_REG(HDMI_CTXSW);
912 DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
913 DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
914 DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
915 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
916 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
917 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
918 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
919 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
920 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
921 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
922 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
923 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
924 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
925 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
926 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
927 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
928 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
929 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
930 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
931 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
932 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
933 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
934 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
935 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
936 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
937 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
938 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
939 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
940 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
941 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
942 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
943 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
944 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
945 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
946 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
947 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
948 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
949 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
950 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
951 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
952 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
953 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
954 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
955 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
956 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
957 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
958 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
959 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
960 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
961 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
962 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
963 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
964 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
965 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
966 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
967 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
968 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
969 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
970 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
971 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
972 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
973 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
974 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
975 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
976 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
977 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
978 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
979 DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
980 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
981 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
982 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
983 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
984 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
985 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
986 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
987 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
988 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
989 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
990 DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
991 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
992 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
993 DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL);
994 DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
995 DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
996 DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
997 DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
998 DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
999 DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
1000 DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
1001 DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
1002 DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
1003 DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
1004 DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
1005 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
1006 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0));
1007 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1));
1008 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2));
1009 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3));
1010 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4));
1011 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5));
1012 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6));
1013 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7));
1014 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8));
1015 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9));
1016 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10));
1017 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11));
1018 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12));
1019 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13));
1020 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14));
1021 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15));
1022 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
1023 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
1024 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
1025 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
1026 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
1027 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
1028 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
1029 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
1030 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
1031 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
1032 DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
1033 DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
1034 DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
1035 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
1036 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
1037 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
1038 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
1039 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
1040 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
1041 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
1042 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
1043 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
1044 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
1045 DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
1046 DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
1047 DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
1048 DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
1049 DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
1050 DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
1051 DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
1052 DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
1053 DUMP_REG(HDMI_NV_PDISP_SCRATCH);
1054 DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
1055 DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
1056 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
1057 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
1058 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
1059 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
1060 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
1061 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
1062 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
1063 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
1064 DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
1065 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
1066 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
1067 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
1068
1069#undef DUMP_REG
1070
1071 return 0;
1072}
1073
1074static struct drm_info_list debugfs_files[] = {
1075 { "regs", tegra_hdmi_show_regs, 0, NULL },
1076};
1077
1078static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi,
1079 struct drm_minor *minor)
1080{
1081 unsigned int i;
1082 int err;
1083
1084 hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root);
1085 if (!hdmi->debugfs)
1086 return -ENOMEM;
1087
1088 hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1089 GFP_KERNEL);
1090 if (!hdmi->debugfs_files) {
1091 err = -ENOMEM;
1092 goto remove;
1093 }
1094
1095 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1096 hdmi->debugfs_files[i].data = hdmi;
1097
1098 err = drm_debugfs_create_files(hdmi->debugfs_files,
1099 ARRAY_SIZE(debugfs_files),
1100 hdmi->debugfs, minor);
1101 if (err < 0)
1102 goto free;
1103
1104 hdmi->minor = minor;
1105
1106 return 0;
1107
1108free:
1109 kfree(hdmi->debugfs_files);
1110 hdmi->debugfs_files = NULL;
1111remove:
1112 debugfs_remove(hdmi->debugfs);
1113 hdmi->debugfs = NULL;
1114
1115 return err;
1116}
1117
1118static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
1119{
1120 drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files),
1121 hdmi->minor);
1122 hdmi->minor = NULL;
1123
1124 kfree(hdmi->debugfs_files);
1125 hdmi->debugfs_files = NULL;
1126
1127 debugfs_remove(hdmi->debugfs);
1128 hdmi->debugfs = NULL;
1129
1130 return 0;
1131}
1132
1133static int tegra_hdmi_drm_init(struct host1x_client *client,
1134 struct drm_device *drm)
1135{
1136 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1137 int err;
1138
1139 hdmi->output.type = TEGRA_OUTPUT_HDMI;
1140 hdmi->output.dev = client->dev;
1141 hdmi->output.ops = &hdmi_ops;
1142
1143 err = tegra_output_init(drm, &hdmi->output);
1144 if (err < 0) {
1145 dev_err(client->dev, "output setup failed: %d\n", err);
1146 return err;
1147 }
1148
1149 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1150 err = tegra_hdmi_debugfs_init(hdmi, drm->primary);
1151 if (err < 0)
1152 dev_err(client->dev, "debugfs setup failed: %d\n", err);
1153 }
1154
1155 return 0;
1156}
1157
1158static int tegra_hdmi_drm_exit(struct host1x_client *client)
1159{
1160 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1161 int err;
1162
1163 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1164 err = tegra_hdmi_debugfs_exit(hdmi);
1165 if (err < 0)
1166 dev_err(client->dev, "debugfs cleanup failed: %d\n",
1167 err);
1168 }
1169
1170 err = tegra_output_disable(&hdmi->output);
1171 if (err < 0) {
1172 dev_err(client->dev, "output failed to disable: %d\n", err);
1173 return err;
1174 }
1175
1176 err = tegra_output_exit(&hdmi->output);
1177 if (err < 0) {
1178 dev_err(client->dev, "output cleanup failed: %d\n", err);
1179 return err;
1180 }
1181
1182 return 0;
1183}
1184
1185static const struct host1x_client_ops hdmi_client_ops = {
1186 .drm_init = tegra_hdmi_drm_init,
1187 .drm_exit = tegra_hdmi_drm_exit,
1188};
1189
1190static int tegra_hdmi_probe(struct platform_device *pdev)
1191{
1192 struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
1193 struct tegra_hdmi *hdmi;
1194 struct resource *regs;
1195 int err;
1196
1197 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
1198 if (!hdmi)
1199 return -ENOMEM;
1200
1201 hdmi->dev = &pdev->dev;
1202 hdmi->audio_source = AUTO;
1203 hdmi->audio_freq = 44100;
1204 hdmi->stereo = false;
1205 hdmi->dvi = false;
1206
1207 hdmi->clk = devm_clk_get(&pdev->dev, NULL);
1208 if (IS_ERR(hdmi->clk)) {
1209 dev_err(&pdev->dev, "failed to get clock\n");
1210 return PTR_ERR(hdmi->clk);
1211 }
1212
1213 err = clk_prepare(hdmi->clk);
1214 if (err < 0)
1215 return err;
1216
1217 hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1218 if (IS_ERR(hdmi->clk_parent))
1219 return PTR_ERR(hdmi->clk_parent);
1220
1221 err = clk_prepare(hdmi->clk_parent);
1222 if (err < 0)
1223 return err;
1224
1225 err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
1226 if (err < 0) {
1227 dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
1228 return err;
1229 }
1230
1231 hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
1232 if (IS_ERR(hdmi->vdd)) {
1233 dev_err(&pdev->dev, "failed to get VDD regulator\n");
1234 return PTR_ERR(hdmi->vdd);
1235 }
1236
1237 hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
1238 if (IS_ERR(hdmi->pll)) {
1239 dev_err(&pdev->dev, "failed to get PLL regulator\n");
1240 return PTR_ERR(hdmi->pll);
1241 }
1242
1243 hdmi->output.dev = &pdev->dev;
1244
1245 err = tegra_output_parse_dt(&hdmi->output);
1246 if (err < 0)
1247 return err;
1248
1249 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1250 if (!regs)
1251 return -ENXIO;
1252
1253 hdmi->regs = devm_ioremap_resource(&pdev->dev, regs);
1254 if (IS_ERR(hdmi->regs))
1255 return PTR_ERR(hdmi->regs);
1256
1257 err = platform_get_irq(pdev, 0);
1258 if (err < 0)
1259 return err;
1260
1261 hdmi->irq = err;
1262
1263 hdmi->client.ops = &hdmi_client_ops;
1264 INIT_LIST_HEAD(&hdmi->client.list);
1265 hdmi->client.dev = &pdev->dev;
1266
1267 err = host1x_register_client(host1x, &hdmi->client);
1268 if (err < 0) {
1269 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1270 err);
1271 return err;
1272 }
1273
1274 platform_set_drvdata(pdev, hdmi);
1275
1276 return 0;
1277}
1278
1279static int tegra_hdmi_remove(struct platform_device *pdev)
1280{
1281 struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
1282 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
1283 int err;
1284
1285 err = host1x_unregister_client(host1x, &hdmi->client);
1286 if (err < 0) {
1287 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1288 err);
1289 return err;
1290 }
1291
1292 clk_unprepare(hdmi->clk_parent);
1293 clk_unprepare(hdmi->clk);
1294
1295 return 0;
1296}
1297
1298static struct of_device_id tegra_hdmi_of_match[] = {
1299 { .compatible = "nvidia,tegra30-hdmi", },
1300 { .compatible = "nvidia,tegra20-hdmi", },
1301 { },
1302};
1303
1304struct platform_driver tegra_hdmi_driver = {
1305 .driver = {
1306 .name = "tegra-hdmi",
1307 .owner = THIS_MODULE,
1308 .of_match_table = tegra_hdmi_of_match,
1309 },
1310 .probe = tegra_hdmi_probe,
1311 .remove = tegra_hdmi_remove,
1312};
diff --git a/drivers/gpu/host1x/drm/hdmi.h b/drivers/gpu/host1x/drm/hdmi.h
new file mode 100644
index 000000000000..52ac36e08ccb
--- /dev/null
+++ b/drivers/gpu/host1x/drm/hdmi.h
@@ -0,0 +1,386 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#ifndef TEGRA_HDMI_H
11#define TEGRA_HDMI_H 1
12
13/* register definitions */
14#define HDMI_CTXSW 0x00
15
16#define HDMI_NV_PDISP_SOR_STATE0 0x01
17#define SOR_STATE_UPDATE (1 << 0)
18
19#define HDMI_NV_PDISP_SOR_STATE1 0x02
20#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE (2 << 0)
21#define SOR_STATE_ASY_ORMODE_NORMAL (1 << 2)
22#define SOR_STATE_ATTACHED (1 << 3)
23
24#define HDMI_NV_PDISP_SOR_STATE2 0x03
25#define SOR_STATE_ASY_OWNER_NONE (0 << 0)
26#define SOR_STATE_ASY_OWNER_HEAD0 (1 << 0)
27#define SOR_STATE_ASY_SUBOWNER_NONE (0 << 4)
28#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0 (1 << 4)
29#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1 (2 << 4)
30#define SOR_STATE_ASY_SUBOWNER_BOTH (3 << 4)
31#define SOR_STATE_ASY_CRCMODE_ACTIVE (0 << 6)
32#define SOR_STATE_ASY_CRCMODE_COMPLETE (1 << 6)
33#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 << 6)
34#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8)
35#define SOR_STATE_ASY_PROTOCOL_CUSTOM (15 << 8)
36#define SOR_STATE_ASY_HSYNCPOL_POS (0 << 12)
37#define SOR_STATE_ASY_HSYNCPOL_NEG (1 << 12)
38#define SOR_STATE_ASY_VSYNCPOL_POS (0 << 13)
39#define SOR_STATE_ASY_VSYNCPOL_NEG (1 << 13)
40#define SOR_STATE_ASY_DEPOL_POS (0 << 14)
41#define SOR_STATE_ASY_DEPOL_NEG (1 << 14)
42
43#define HDMI_NV_PDISP_RG_HDCP_AN_MSB 0x04
44#define HDMI_NV_PDISP_RG_HDCP_AN_LSB 0x05
45#define HDMI_NV_PDISP_RG_HDCP_CN_MSB 0x06
46#define HDMI_NV_PDISP_RG_HDCP_CN_LSB 0x07
47#define HDMI_NV_PDISP_RG_HDCP_AKSV_MSB 0x08
48#define HDMI_NV_PDISP_RG_HDCP_AKSV_LSB 0x09
49#define HDMI_NV_PDISP_RG_HDCP_BKSV_MSB 0x0a
50#define HDMI_NV_PDISP_RG_HDCP_BKSV_LSB 0x0b
51#define HDMI_NV_PDISP_RG_HDCP_CKSV_MSB 0x0c
52#define HDMI_NV_PDISP_RG_HDCP_CKSV_LSB 0x0d
53#define HDMI_NV_PDISP_RG_HDCP_DKSV_MSB 0x0e
54#define HDMI_NV_PDISP_RG_HDCP_DKSV_LSB 0x0f
55#define HDMI_NV_PDISP_RG_HDCP_CTRL 0x10
56#define HDMI_NV_PDISP_RG_HDCP_CMODE 0x11
57#define HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB 0x12
58#define HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB 0x13
59#define HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB 0x14
60#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2 0x15
61#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1 0x16
62#define HDMI_NV_PDISP_RG_HDCP_RI 0x17
63#define HDMI_NV_PDISP_RG_HDCP_CS_MSB 0x18
64#define HDMI_NV_PDISP_RG_HDCP_CS_LSB 0x19
65#define HDMI_NV_PDISP_HDMI_AUDIO_EMU0 0x1a
66#define HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0 0x1b
67#define HDMI_NV_PDISP_HDMI_AUDIO_EMU1 0x1c
68#define HDMI_NV_PDISP_HDMI_AUDIO_EMU2 0x1d
69
70#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL 0x1e
71#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS 0x1f
72#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER 0x20
73#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW 0x21
74#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH 0x22
75#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL 0x23
76#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS 0x24
77#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER 0x25
78#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW 0x26
79#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH 0x27
80#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW 0x28
81#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH 0x29
82
83#define INFOFRAME_CTRL_ENABLE (1 << 0)
84
85#define INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0)
86#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8)
87#define INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
88
89#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL 0x2a
90#define GENERIC_CTRL_ENABLE (1 << 0)
91#define GENERIC_CTRL_OTHER (1 << 4)
92#define GENERIC_CTRL_SINGLE (1 << 8)
93#define GENERIC_CTRL_HBLANK (1 << 12)
94#define GENERIC_CTRL_AUDIO (1 << 16)
95
96#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS 0x2b
97#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER 0x2c
98#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW 0x2d
99#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH 0x2e
100#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW 0x2f
101#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH 0x30
102#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW 0x31
103#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH 0x32
104#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW 0x33
105#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH 0x34
106
107#define HDMI_NV_PDISP_HDMI_ACR_CTRL 0x35
108#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW 0x36
109#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH 0x37
110#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW 0x38
111#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH 0x39
112#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW 0x3a
113#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH 0x3b
114#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW 0x3c
115#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH 0x3d
116#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW 0x3e
117#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH 0x3f
118#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW 0x40
119#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH 0x41
120#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW 0x42
121#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH 0x43
122
123#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8)
124#define ACR_SUBPACK_N(x) (((x) & 0xffffff) << 0)
125#define ACR_ENABLE (1 << 31)
126
127#define HDMI_NV_PDISP_HDMI_CTRL 0x44
128#define HDMI_CTRL_REKEY(x) (((x) & 0x7f) << 0)
129#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16)
130#define HDMI_CTRL_ENABLE (1 << 30)
131
132#define HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT 0x45
133#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW 0x46
134#define VSYNC_WINDOW_END(x) (((x) & 0x3ff) << 0)
135#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16)
136#define VSYNC_WINDOW_ENABLE (1 << 31)
137
138#define HDMI_NV_PDISP_HDMI_GCP_CTRL 0x47
139#define HDMI_NV_PDISP_HDMI_GCP_STATUS 0x48
140#define HDMI_NV_PDISP_HDMI_GCP_SUBPACK 0x49
141#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1 0x4a
142#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2 0x4b
143#define HDMI_NV_PDISP_HDMI_EMU0 0x4c
144#define HDMI_NV_PDISP_HDMI_EMU1 0x4d
145#define HDMI_NV_PDISP_HDMI_EMU1_RDATA 0x4e
146
147#define HDMI_NV_PDISP_HDMI_SPARE 0x4f
148#define SPARE_HW_CTS (1 << 0)
149#define SPARE_FORCE_SW_CTS (1 << 1)
150#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16)
151
152#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1 0x50
153#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2 0x51
154#define HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL 0x53
155#define HDMI_NV_PDISP_SOR_CAP 0x54
156#define HDMI_NV_PDISP_SOR_PWR 0x55
157#define SOR_PWR_NORMAL_STATE_PD (0 << 0)
158#define SOR_PWR_NORMAL_STATE_PU (1 << 0)
159#define SOR_PWR_NORMAL_START_NORMAL (0 << 1)
160#define SOR_PWR_NORMAL_START_ALT (1 << 1)
161#define SOR_PWR_SAFE_STATE_PD (0 << 16)
162#define SOR_PWR_SAFE_STATE_PU (1 << 16)
163#define SOR_PWR_SETTING_NEW_DONE (0 << 31)
164#define SOR_PWR_SETTING_NEW_PENDING (1 << 31)
165#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31)
166
167#define HDMI_NV_PDISP_SOR_TEST 0x56
168#define HDMI_NV_PDISP_SOR_PLL0 0x57
169#define SOR_PLL_PWR (1 << 0)
170#define SOR_PLL_PDBG (1 << 1)
171#define SOR_PLL_VCAPD (1 << 2)
172#define SOR_PLL_PDPORT (1 << 3)
173#define SOR_PLL_RESISTORSEL (1 << 4)
174#define SOR_PLL_PULLDOWN (1 << 5)
175#define SOR_PLL_VCOCAP(x) (((x) & 0xf) << 8)
176#define SOR_PLL_BG_V17_S(x) (((x) & 0xf) << 12)
177#define SOR_PLL_FILTER(x) (((x) & 0xf) << 16)
178#define SOR_PLL_ICHPMP(x) (((x) & 0xf) << 24)
179#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0xf) << 28)
180
181#define HDMI_NV_PDISP_SOR_PLL1 0x58
182#define SOR_PLL_TMDS_TERM_ENABLE (1 << 8)
183#define SOR_PLL_TMDS_TERMADJ(x) (((x) & 0xf) << 9)
184#define SOR_PLL_LOADADJ(x) (((x) & 0xf) << 20)
185#define SOR_PLL_PE_EN (1 << 28)
186#define SOR_PLL_HALF_FULL_PE (1 << 29)
187#define SOR_PLL_S_D_PIN_PE (1 << 30)
188
189#define HDMI_NV_PDISP_SOR_PLL2 0x59
190
191#define HDMI_NV_PDISP_SOR_CSTM 0x5a
192#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24)
193
194#define HDMI_NV_PDISP_SOR_LVDS 0x5b
195#define HDMI_NV_PDISP_SOR_CRCA 0x5c
196#define HDMI_NV_PDISP_SOR_CRCB 0x5d
197#define HDMI_NV_PDISP_SOR_BLANK 0x5e
198#define HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f
199#define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) << 0)
200#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4)
201#define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8)
202#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
203#define SOR_SEQ_PC(x) (((x) & 0xf) << 16)
204#define SOR_SEQ_STATUS (1 << 28)
205#define SOR_SEQ_SWITCH (1 << 30)
206
207#define HDMI_NV_PDISP_SOR_SEQ_INST(x) (0x60 + (x))
208
209#define SOR_SEQ_INST_WAIT_TIME(x) (((x) & 0x3ff) << 0)
210#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12)
211#define SOR_SEQ_INST_HALT (1 << 15)
212#define SOR_SEQ_INST_PIN_A_LOW (0 << 21)
213#define SOR_SEQ_INST_PIN_A_HIGH (1 << 21)
214#define SOR_SEQ_INST_PIN_B_LOW (0 << 22)
215#define SOR_SEQ_INST_PIN_B_HIGH (1 << 22)
216#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23)
217
218#define HDMI_NV_PDISP_SOR_VCRCA0 0x72
219#define HDMI_NV_PDISP_SOR_VCRCA1 0x73
220#define HDMI_NV_PDISP_SOR_CCRCA0 0x74
221#define HDMI_NV_PDISP_SOR_CCRCA1 0x75
222#define HDMI_NV_PDISP_SOR_EDATAA0 0x76
223#define HDMI_NV_PDISP_SOR_EDATAA1 0x77
224#define HDMI_NV_PDISP_SOR_COUNTA0 0x78
225#define HDMI_NV_PDISP_SOR_COUNTA1 0x79
226#define HDMI_NV_PDISP_SOR_DEBUGA0 0x7a
227#define HDMI_NV_PDISP_SOR_DEBUGA1 0x7b
228#define HDMI_NV_PDISP_SOR_TRIG 0x7c
229#define HDMI_NV_PDISP_SOR_MSCHECK 0x7d
230
231#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT 0x7e
232#define DRIVE_CURRENT_LANE0(x) (((x) & 0x3f) << 0)
233#define DRIVE_CURRENT_LANE1(x) (((x) & 0x3f) << 8)
234#define DRIVE_CURRENT_LANE2(x) (((x) & 0x3f) << 16)
235#define DRIVE_CURRENT_LANE3(x) (((x) & 0x3f) << 24)
236#define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
237
238#define DRIVE_CURRENT_1_500_mA 0x00
239#define DRIVE_CURRENT_1_875_mA 0x01
240#define DRIVE_CURRENT_2_250_mA 0x02
241#define DRIVE_CURRENT_2_625_mA 0x03
242#define DRIVE_CURRENT_3_000_mA 0x04
243#define DRIVE_CURRENT_3_375_mA 0x05
244#define DRIVE_CURRENT_3_750_mA 0x06
245#define DRIVE_CURRENT_4_125_mA 0x07
246#define DRIVE_CURRENT_4_500_mA 0x08
247#define DRIVE_CURRENT_4_875_mA 0x09
248#define DRIVE_CURRENT_5_250_mA 0x0a
249#define DRIVE_CURRENT_5_625_mA 0x0b
250#define DRIVE_CURRENT_6_000_mA 0x0c
251#define DRIVE_CURRENT_6_375_mA 0x0d
252#define DRIVE_CURRENT_6_750_mA 0x0e
253#define DRIVE_CURRENT_7_125_mA 0x0f
254#define DRIVE_CURRENT_7_500_mA 0x10
255#define DRIVE_CURRENT_7_875_mA 0x11
256#define DRIVE_CURRENT_8_250_mA 0x12
257#define DRIVE_CURRENT_8_625_mA 0x13
258#define DRIVE_CURRENT_9_000_mA 0x14
259#define DRIVE_CURRENT_9_375_mA 0x15
260#define DRIVE_CURRENT_9_750_mA 0x16
261#define DRIVE_CURRENT_10_125_mA 0x17
262#define DRIVE_CURRENT_10_500_mA 0x18
263#define DRIVE_CURRENT_10_875_mA 0x19
264#define DRIVE_CURRENT_11_250_mA 0x1a
265#define DRIVE_CURRENT_11_625_mA 0x1b
266#define DRIVE_CURRENT_12_000_mA 0x1c
267#define DRIVE_CURRENT_12_375_mA 0x1d
268#define DRIVE_CURRENT_12_750_mA 0x1e
269#define DRIVE_CURRENT_13_125_mA 0x1f
270#define DRIVE_CURRENT_13_500_mA 0x20
271#define DRIVE_CURRENT_13_875_mA 0x21
272#define DRIVE_CURRENT_14_250_mA 0x22
273#define DRIVE_CURRENT_14_625_mA 0x23
274#define DRIVE_CURRENT_15_000_mA 0x24
275#define DRIVE_CURRENT_15_375_mA 0x25
276#define DRIVE_CURRENT_15_750_mA 0x26
277#define DRIVE_CURRENT_16_125_mA 0x27
278#define DRIVE_CURRENT_16_500_mA 0x28
279#define DRIVE_CURRENT_16_875_mA 0x29
280#define DRIVE_CURRENT_17_250_mA 0x2a
281#define DRIVE_CURRENT_17_625_mA 0x2b
282#define DRIVE_CURRENT_18_000_mA 0x2c
283#define DRIVE_CURRENT_18_375_mA 0x2d
284#define DRIVE_CURRENT_18_750_mA 0x2e
285#define DRIVE_CURRENT_19_125_mA 0x2f
286#define DRIVE_CURRENT_19_500_mA 0x30
287#define DRIVE_CURRENT_19_875_mA 0x31
288#define DRIVE_CURRENT_20_250_mA 0x32
289#define DRIVE_CURRENT_20_625_mA 0x33
290#define DRIVE_CURRENT_21_000_mA 0x34
291#define DRIVE_CURRENT_21_375_mA 0x35
292#define DRIVE_CURRENT_21_750_mA 0x36
293#define DRIVE_CURRENT_22_125_mA 0x37
294#define DRIVE_CURRENT_22_500_mA 0x38
295#define DRIVE_CURRENT_22_875_mA 0x39
296#define DRIVE_CURRENT_23_250_mA 0x3a
297#define DRIVE_CURRENT_23_625_mA 0x3b
298#define DRIVE_CURRENT_24_000_mA 0x3c
299#define DRIVE_CURRENT_24_375_mA 0x3d
300#define DRIVE_CURRENT_24_750_mA 0x3e
301
302#define HDMI_NV_PDISP_AUDIO_DEBUG0 0x7f
303#define HDMI_NV_PDISP_AUDIO_DEBUG1 0x80
304#define HDMI_NV_PDISP_AUDIO_DEBUG2 0x81
305
306#define HDMI_NV_PDISP_AUDIO_FS(x) (0x82 + (x))
307#define AUDIO_FS_LOW(x) (((x) & 0xfff) << 0)
308#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16)
309
310#define HDMI_NV_PDISP_AUDIO_PULSE_WIDTH 0x89
311#define HDMI_NV_PDISP_AUDIO_THRESHOLD 0x8a
312#define HDMI_NV_PDISP_AUDIO_CNTRL0 0x8b
313#define AUDIO_CNTRL0_ERROR_TOLERANCE(x) (((x) & 0xff) << 0)
314#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO (0 << 20)
315#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
316#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL (2 << 20)
317#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24)
318
319#define HDMI_NV_PDISP_AUDIO_N 0x8c
320#define AUDIO_N_VALUE(x) (((x) & 0xfffff) << 0)
321#define AUDIO_N_RESETF (1 << 20)
322#define AUDIO_N_GENERATE_NORMAL (0 << 24)
323#define AUDIO_N_GENERATE_ALTERNATE (1 << 24)
324
325#define HDMI_NV_PDISP_HDCPRIF_ROM_TIMING 0x94
326#define HDMI_NV_PDISP_SOR_REFCLK 0x95
327#define SOR_REFCLK_DIV_INT(x) (((x) & 0xff) << 8)
328#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6)
329
330#define HDMI_NV_PDISP_CRC_CONTROL 0x96
331#define HDMI_NV_PDISP_INPUT_CONTROL 0x97
332#define HDMI_SRC_DISPLAYA (0 << 0)
333#define HDMI_SRC_DISPLAYB (1 << 0)
334#define ARM_VIDEO_RANGE_FULL (0 << 1)
335#define ARM_VIDEO_RANGE_LIMITED (1 << 1)
336
337#define HDMI_NV_PDISP_SCRATCH 0x98
338#define HDMI_NV_PDISP_PE_CURRENT 0x99
339#define PE_CURRENT0(x) (((x) & 0xf) << 0)
340#define PE_CURRENT1(x) (((x) & 0xf) << 8)
341#define PE_CURRENT2(x) (((x) & 0xf) << 16)
342#define PE_CURRENT3(x) (((x) & 0xf) << 24)
343
344#define PE_CURRENT_0_0_mA 0x0
345#define PE_CURRENT_0_5_mA 0x1
346#define PE_CURRENT_1_0_mA 0x2
347#define PE_CURRENT_1_5_mA 0x3
348#define PE_CURRENT_2_0_mA 0x4
349#define PE_CURRENT_2_5_mA 0x5
350#define PE_CURRENT_3_0_mA 0x6
351#define PE_CURRENT_3_5_mA 0x7
352#define PE_CURRENT_4_0_mA 0x8
353#define PE_CURRENT_4_5_mA 0x9
354#define PE_CURRENT_5_0_mA 0xa
355#define PE_CURRENT_5_5_mA 0xb
356#define PE_CURRENT_6_0_mA 0xc
357#define PE_CURRENT_6_5_mA 0xd
358#define PE_CURRENT_7_0_mA 0xe
359#define PE_CURRENT_7_5_mA 0xf
360
361#define HDMI_NV_PDISP_KEY_CTRL 0x9a
362#define HDMI_NV_PDISP_KEY_DEBUG0 0x9b
363#define HDMI_NV_PDISP_KEY_DEBUG1 0x9c
364#define HDMI_NV_PDISP_KEY_DEBUG2 0x9d
365#define HDMI_NV_PDISP_KEY_HDCP_KEY_0 0x9e
366#define HDMI_NV_PDISP_KEY_HDCP_KEY_1 0x9f
367#define HDMI_NV_PDISP_KEY_HDCP_KEY_2 0xa0
368#define HDMI_NV_PDISP_KEY_HDCP_KEY_3 0xa1
369#define HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG 0xa2
370#define HDMI_NV_PDISP_KEY_SKEY_INDEX 0xa3
371
372#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0 0xac
373#define AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29)
374#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR 0xbc
375#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE 0xbd
376
377#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320 0xbf
378#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441 0xc0
379#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882 0xc1
380#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764 0xc2
381#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480 0xc3
382#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960 0xc4
383#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920 0xc5
384#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT 0xc5
385
386#endif /* TEGRA_HDMI_H */
diff --git a/drivers/gpu/host1x/drm/host1x.c b/drivers/gpu/host1x/drm/host1x.c
new file mode 100644
index 000000000000..92e25a7e00ea
--- /dev/null
+++ b/drivers/gpu/host1x/drm/host1x.c
@@ -0,0 +1,327 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/clk.h>
11#include <linux/err.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15
16#include "drm.h"
17
18struct host1x_drm_client {
19 struct host1x_client *client;
20 struct device_node *np;
21 struct list_head list;
22};
23
24static int host1x_add_drm_client(struct host1x *host1x, struct device_node *np)
25{
26 struct host1x_drm_client *client;
27
28 client = kzalloc(sizeof(*client), GFP_KERNEL);
29 if (!client)
30 return -ENOMEM;
31
32 INIT_LIST_HEAD(&client->list);
33 client->np = of_node_get(np);
34
35 list_add_tail(&client->list, &host1x->drm_clients);
36
37 return 0;
38}
39
40static int host1x_activate_drm_client(struct host1x *host1x,
41 struct host1x_drm_client *drm,
42 struct host1x_client *client)
43{
44 mutex_lock(&host1x->drm_clients_lock);
45 list_del_init(&drm->list);
46 list_add_tail(&drm->list, &host1x->drm_active);
47 drm->client = client;
48 mutex_unlock(&host1x->drm_clients_lock);
49
50 return 0;
51}
52
53static int host1x_remove_drm_client(struct host1x *host1x,
54 struct host1x_drm_client *client)
55{
56 mutex_lock(&host1x->drm_clients_lock);
57 list_del_init(&client->list);
58 mutex_unlock(&host1x->drm_clients_lock);
59
60 of_node_put(client->np);
61 kfree(client);
62
63 return 0;
64}
65
66static int host1x_parse_dt(struct host1x *host1x)
67{
68 static const char * const compat[] = {
69 "nvidia,tegra20-dc",
70 "nvidia,tegra20-hdmi",
71 "nvidia,tegra30-dc",
72 "nvidia,tegra30-hdmi",
73 };
74 unsigned int i;
75 int err;
76
77 for (i = 0; i < ARRAY_SIZE(compat); i++) {
78 struct device_node *np;
79
80 for_each_child_of_node(host1x->dev->of_node, np) {
81 if (of_device_is_compatible(np, compat[i]) &&
82 of_device_is_available(np)) {
83 err = host1x_add_drm_client(host1x, np);
84 if (err < 0)
85 return err;
86 }
87 }
88 }
89
90 return 0;
91}
92
93static int tegra_host1x_probe(struct platform_device *pdev)
94{
95 struct host1x *host1x;
96 struct resource *regs;
97 int err;
98
99 host1x = devm_kzalloc(&pdev->dev, sizeof(*host1x), GFP_KERNEL);
100 if (!host1x)
101 return -ENOMEM;
102
103 mutex_init(&host1x->drm_clients_lock);
104 INIT_LIST_HEAD(&host1x->drm_clients);
105 INIT_LIST_HEAD(&host1x->drm_active);
106 mutex_init(&host1x->clients_lock);
107 INIT_LIST_HEAD(&host1x->clients);
108 host1x->dev = &pdev->dev;
109
110 err = host1x_parse_dt(host1x);
111 if (err < 0) {
112 dev_err(&pdev->dev, "failed to parse DT: %d\n", err);
113 return err;
114 }
115
116 host1x->clk = devm_clk_get(&pdev->dev, NULL);
117 if (IS_ERR(host1x->clk))
118 return PTR_ERR(host1x->clk);
119
120 err = clk_prepare_enable(host1x->clk);
121 if (err < 0)
122 return err;
123
124 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
125 if (!regs) {
126 err = -ENXIO;
127 goto err;
128 }
129
130 err = platform_get_irq(pdev, 0);
131 if (err < 0)
132 goto err;
133
134 host1x->syncpt = err;
135
136 err = platform_get_irq(pdev, 1);
137 if (err < 0)
138 goto err;
139
140 host1x->irq = err;
141
142 host1x->regs = devm_ioremap_resource(&pdev->dev, regs);
143 if (IS_ERR(host1x->regs)) {
144 err = PTR_ERR(host1x->regs);
145 goto err;
146 }
147
148 platform_set_drvdata(pdev, host1x);
149
150 return 0;
151
152err:
153 clk_disable_unprepare(host1x->clk);
154 return err;
155}
156
157static int tegra_host1x_remove(struct platform_device *pdev)
158{
159 struct host1x *host1x = platform_get_drvdata(pdev);
160
161 clk_disable_unprepare(host1x->clk);
162
163 return 0;
164}
165
166int host1x_drm_init(struct host1x *host1x, struct drm_device *drm)
167{
168 struct host1x_client *client;
169
170 mutex_lock(&host1x->clients_lock);
171
172 list_for_each_entry(client, &host1x->clients, list) {
173 if (client->ops && client->ops->drm_init) {
174 int err = client->ops->drm_init(client, drm);
175 if (err < 0) {
176 dev_err(host1x->dev,
177 "DRM setup failed for %s: %d\n",
178 dev_name(client->dev), err);
179 return err;
180 }
181 }
182 }
183
184 mutex_unlock(&host1x->clients_lock);
185
186 return 0;
187}
188
189int host1x_drm_exit(struct host1x *host1x)
190{
191 struct platform_device *pdev = to_platform_device(host1x->dev);
192 struct host1x_client *client;
193
194 if (!host1x->drm)
195 return 0;
196
197 mutex_lock(&host1x->clients_lock);
198
199 list_for_each_entry_reverse(client, &host1x->clients, list) {
200 if (client->ops && client->ops->drm_exit) {
201 int err = client->ops->drm_exit(client);
202 if (err < 0) {
203 dev_err(host1x->dev,
204 "DRM cleanup failed for %s: %d\n",
205 dev_name(client->dev), err);
206 return err;
207 }
208 }
209 }
210
211 mutex_unlock(&host1x->clients_lock);
212
213 drm_platform_exit(&tegra_drm_driver, pdev);
214 host1x->drm = NULL;
215
216 return 0;
217}
218
219int host1x_register_client(struct host1x *host1x, struct host1x_client *client)
220{
221 struct host1x_drm_client *drm, *tmp;
222 int err;
223
224 mutex_lock(&host1x->clients_lock);
225 list_add_tail(&client->list, &host1x->clients);
226 mutex_unlock(&host1x->clients_lock);
227
228 list_for_each_entry_safe(drm, tmp, &host1x->drm_clients, list)
229 if (drm->np == client->dev->of_node)
230 host1x_activate_drm_client(host1x, drm, client);
231
232 if (list_empty(&host1x->drm_clients)) {
233 struct platform_device *pdev = to_platform_device(host1x->dev);
234
235 err = drm_platform_init(&tegra_drm_driver, pdev);
236 if (err < 0) {
237 dev_err(host1x->dev, "drm_platform_init(): %d\n", err);
238 return err;
239 }
240 }
241
242 client->host1x = host1x;
243
244 return 0;
245}
246
247int host1x_unregister_client(struct host1x *host1x,
248 struct host1x_client *client)
249{
250 struct host1x_drm_client *drm, *tmp;
251 int err;
252
253 list_for_each_entry_safe(drm, tmp, &host1x->drm_active, list) {
254 if (drm->client == client) {
255 err = host1x_drm_exit(host1x);
256 if (err < 0) {
257 dev_err(host1x->dev, "host1x_drm_exit(): %d\n",
258 err);
259 return err;
260 }
261
262 host1x_remove_drm_client(host1x, drm);
263 break;
264 }
265 }
266
267 mutex_lock(&host1x->clients_lock);
268 list_del_init(&client->list);
269 mutex_unlock(&host1x->clients_lock);
270
271 return 0;
272}
273
274static struct of_device_id tegra_host1x_of_match[] = {
275 { .compatible = "nvidia,tegra30-host1x", },
276 { .compatible = "nvidia,tegra20-host1x", },
277 { },
278};
279MODULE_DEVICE_TABLE(of, tegra_host1x_of_match);
280
281struct platform_driver tegra_host1x_driver = {
282 .driver = {
283 .name = "tegra-host1x",
284 .owner = THIS_MODULE,
285 .of_match_table = tegra_host1x_of_match,
286 },
287 .probe = tegra_host1x_probe,
288 .remove = tegra_host1x_remove,
289};
290
291static int __init tegra_host1x_init(void)
292{
293 int err;
294
295 err = platform_driver_register(&tegra_host1x_driver);
296 if (err < 0)
297 return err;
298
299 err = platform_driver_register(&tegra_dc_driver);
300 if (err < 0)
301 goto unregister_host1x;
302
303 err = platform_driver_register(&tegra_hdmi_driver);
304 if (err < 0)
305 goto unregister_dc;
306
307 return 0;
308
309unregister_dc:
310 platform_driver_unregister(&tegra_dc_driver);
311unregister_host1x:
312 platform_driver_unregister(&tegra_host1x_driver);
313 return err;
314}
315module_init(tegra_host1x_init);
316
317static void __exit tegra_host1x_exit(void)
318{
319 platform_driver_unregister(&tegra_hdmi_driver);
320 platform_driver_unregister(&tegra_dc_driver);
321 platform_driver_unregister(&tegra_host1x_driver);
322}
323module_exit(tegra_host1x_exit);
324
325MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
326MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
327MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/host1x/drm/output.c
new file mode 100644
index 000000000000..8140fc6c34d8
--- /dev/null
+++ b/drivers/gpu/host1x/drm/output.c
@@ -0,0 +1,272 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/of_gpio.h>
12#include <linux/of_i2c.h>
13
14#include "drm.h"
15
16static int tegra_connector_get_modes(struct drm_connector *connector)
17{
18 struct tegra_output *output = connector_to_output(connector);
19 struct edid *edid = NULL;
20 int err = 0;
21
22 if (output->edid)
23 edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
24 else if (output->ddc)
25 edid = drm_get_edid(connector, output->ddc);
26
27 drm_mode_connector_update_edid_property(connector, edid);
28
29 if (edid) {
30 err = drm_add_edid_modes(connector, edid);
31 kfree(edid);
32 }
33
34 return err;
35}
36
37static int tegra_connector_mode_valid(struct drm_connector *connector,
38 struct drm_display_mode *mode)
39{
40 struct tegra_output *output = connector_to_output(connector);
41 enum drm_mode_status status = MODE_OK;
42 int err;
43
44 err = tegra_output_check_mode(output, mode, &status);
45 if (err < 0)
46 return MODE_ERROR;
47
48 return status;
49}
50
51static struct drm_encoder *
52tegra_connector_best_encoder(struct drm_connector *connector)
53{
54 struct tegra_output *output = connector_to_output(connector);
55
56 return &output->encoder;
57}
58
59static const struct drm_connector_helper_funcs connector_helper_funcs = {
60 .get_modes = tegra_connector_get_modes,
61 .mode_valid = tegra_connector_mode_valid,
62 .best_encoder = tegra_connector_best_encoder,
63};
64
65static enum drm_connector_status
66tegra_connector_detect(struct drm_connector *connector, bool force)
67{
68 struct tegra_output *output = connector_to_output(connector);
69 enum drm_connector_status status = connector_status_unknown;
70
71 if (gpio_is_valid(output->hpd_gpio)) {
72 if (gpio_get_value(output->hpd_gpio) == 0)
73 status = connector_status_disconnected;
74 else
75 status = connector_status_connected;
76 } else {
77 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
78 status = connector_status_connected;
79 }
80
81 return status;
82}
83
84static void tegra_connector_destroy(struct drm_connector *connector)
85{
86 drm_sysfs_connector_remove(connector);
87 drm_connector_cleanup(connector);
88}
89
90static const struct drm_connector_funcs connector_funcs = {
91 .dpms = drm_helper_connector_dpms,
92 .detect = tegra_connector_detect,
93 .fill_modes = drm_helper_probe_single_connector_modes,
94 .destroy = tegra_connector_destroy,
95};
96
97static void tegra_encoder_destroy(struct drm_encoder *encoder)
98{
99 drm_encoder_cleanup(encoder);
100}
101
102static const struct drm_encoder_funcs encoder_funcs = {
103 .destroy = tegra_encoder_destroy,
104};
105
106static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
107{
108}
109
110static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
111 const struct drm_display_mode *mode,
112 struct drm_display_mode *adjusted)
113{
114 return true;
115}
116
117static void tegra_encoder_prepare(struct drm_encoder *encoder)
118{
119}
120
121static void tegra_encoder_commit(struct drm_encoder *encoder)
122{
123}
124
125static void tegra_encoder_mode_set(struct drm_encoder *encoder,
126 struct drm_display_mode *mode,
127 struct drm_display_mode *adjusted)
128{
129 struct tegra_output *output = encoder_to_output(encoder);
130 int err;
131
132 err = tegra_output_enable(output);
133 if (err < 0)
134 dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err);
135}
136
137static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
138 .dpms = tegra_encoder_dpms,
139 .mode_fixup = tegra_encoder_mode_fixup,
140 .prepare = tegra_encoder_prepare,
141 .commit = tegra_encoder_commit,
142 .mode_set = tegra_encoder_mode_set,
143};
144
145static irqreturn_t hpd_irq(int irq, void *data)
146{
147 struct tegra_output *output = data;
148
149 drm_helper_hpd_irq_event(output->connector.dev);
150
151 return IRQ_HANDLED;
152}
153
154int tegra_output_parse_dt(struct tegra_output *output)
155{
156 enum of_gpio_flags flags;
157 struct device_node *ddc;
158 size_t size;
159 int err;
160
161 if (!output->of_node)
162 output->of_node = output->dev->of_node;
163
164 output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
165
166 ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
167 if (ddc) {
168 output->ddc = of_find_i2c_adapter_by_node(ddc);
169 if (!output->ddc) {
170 err = -EPROBE_DEFER;
171 of_node_put(ddc);
172 return err;
173 }
174
175 of_node_put(ddc);
176 }
177
178 if (!output->edid && !output->ddc)
179 return -ENODEV;
180
181 output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
182 "nvidia,hpd-gpio", 0,
183 &flags);
184
185 return 0;
186}
187
188int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
189{
190 int connector, encoder, err;
191
192 if (gpio_is_valid(output->hpd_gpio)) {
193 unsigned long flags;
194
195 err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN,
196 "HDMI hotplug detect");
197 if (err < 0) {
198 dev_err(output->dev, "gpio_request_one(): %d\n", err);
199 return err;
200 }
201
202 err = gpio_to_irq(output->hpd_gpio);
203 if (err < 0) {
204 dev_err(output->dev, "gpio_to_irq(): %d\n", err);
205 goto free_hpd;
206 }
207
208 output->hpd_irq = err;
209
210 flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
211 IRQF_ONESHOT;
212
213 err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
214 flags, "hpd", output);
215 if (err < 0) {
216 dev_err(output->dev, "failed to request IRQ#%u: %d\n",
217 output->hpd_irq, err);
218 goto free_hpd;
219 }
220
221 output->connector.polled = DRM_CONNECTOR_POLL_HPD;
222 }
223
224 switch (output->type) {
225 case TEGRA_OUTPUT_RGB:
226 connector = DRM_MODE_CONNECTOR_LVDS;
227 encoder = DRM_MODE_ENCODER_LVDS;
228 break;
229
230 case TEGRA_OUTPUT_HDMI:
231 connector = DRM_MODE_CONNECTOR_HDMIA;
232 encoder = DRM_MODE_ENCODER_TMDS;
233 break;
234
235 default:
236 connector = DRM_MODE_CONNECTOR_Unknown;
237 encoder = DRM_MODE_ENCODER_NONE;
238 break;
239 }
240
241 drm_connector_init(drm, &output->connector, &connector_funcs,
242 connector);
243 drm_connector_helper_add(&output->connector, &connector_helper_funcs);
244
245 drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
246 drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
247
248 drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
249 drm_sysfs_connector_add(&output->connector);
250
251 output->encoder.possible_crtcs = 0x3;
252
253 return 0;
254
255free_hpd:
256 gpio_free(output->hpd_gpio);
257
258 return err;
259}
260
261int tegra_output_exit(struct tegra_output *output)
262{
263 if (gpio_is_valid(output->hpd_gpio)) {
264 free_irq(output->hpd_irq, output);
265 gpio_free(output->hpd_gpio);
266 }
267
268 if (output->ddc)
269 put_device(&output->ddc->dev);
270
271 return 0;
272}
diff --git a/drivers/gpu/host1x/drm/rgb.c b/drivers/gpu/host1x/drm/rgb.c
new file mode 100644
index 000000000000..ed4416f20260
--- /dev/null
+++ b/drivers/gpu/host1x/drm/rgb.c
@@ -0,0 +1,228 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/clk.h>
11#include <linux/module.h>
12#include <linux/of.h>
13#include <linux/platform_device.h>
14
15#include "drm.h"
16#include "dc.h"
17
18struct tegra_rgb {
19 struct tegra_output output;
20 struct clk *clk_parent;
21 struct clk *clk;
22};
23
24static inline struct tegra_rgb *to_rgb(struct tegra_output *output)
25{
26 return container_of(output, struct tegra_rgb, output);
27}
28
29struct reg_entry {
30 unsigned long offset;
31 unsigned long value;
32};
33
34static const struct reg_entry rgb_enable[] = {
35 { DC_COM_PIN_OUTPUT_ENABLE(0), 0x00000000 },
36 { DC_COM_PIN_OUTPUT_ENABLE(1), 0x00000000 },
37 { DC_COM_PIN_OUTPUT_ENABLE(2), 0x00000000 },
38 { DC_COM_PIN_OUTPUT_ENABLE(3), 0x00000000 },
39 { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
40 { DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 },
41 { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
42 { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
43 { DC_COM_PIN_OUTPUT_DATA(0), 0x00000000 },
44 { DC_COM_PIN_OUTPUT_DATA(1), 0x00000000 },
45 { DC_COM_PIN_OUTPUT_DATA(2), 0x00000000 },
46 { DC_COM_PIN_OUTPUT_DATA(3), 0x00000000 },
47 { DC_COM_PIN_OUTPUT_SELECT(0), 0x00000000 },
48 { DC_COM_PIN_OUTPUT_SELECT(1), 0x00000000 },
49 { DC_COM_PIN_OUTPUT_SELECT(2), 0x00000000 },
50 { DC_COM_PIN_OUTPUT_SELECT(3), 0x00000000 },
51 { DC_COM_PIN_OUTPUT_SELECT(4), 0x00210222 },
52 { DC_COM_PIN_OUTPUT_SELECT(5), 0x00002200 },
53 { DC_COM_PIN_OUTPUT_SELECT(6), 0x00020000 },
54};
55
56static const struct reg_entry rgb_disable[] = {
57 { DC_COM_PIN_OUTPUT_SELECT(6), 0x00000000 },
58 { DC_COM_PIN_OUTPUT_SELECT(5), 0x00000000 },
59 { DC_COM_PIN_OUTPUT_SELECT(4), 0x00000000 },
60 { DC_COM_PIN_OUTPUT_SELECT(3), 0x00000000 },
61 { DC_COM_PIN_OUTPUT_SELECT(2), 0x00000000 },
62 { DC_COM_PIN_OUTPUT_SELECT(1), 0x00000000 },
63 { DC_COM_PIN_OUTPUT_SELECT(0), 0x00000000 },
64 { DC_COM_PIN_OUTPUT_DATA(3), 0xaaaaaaaa },
65 { DC_COM_PIN_OUTPUT_DATA(2), 0xaaaaaaaa },
66 { DC_COM_PIN_OUTPUT_DATA(1), 0xaaaaaaaa },
67 { DC_COM_PIN_OUTPUT_DATA(0), 0xaaaaaaaa },
68 { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
69 { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
70 { DC_COM_PIN_OUTPUT_POLARITY(1), 0x00000000 },
71 { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
72 { DC_COM_PIN_OUTPUT_ENABLE(3), 0x55555555 },
73 { DC_COM_PIN_OUTPUT_ENABLE(2), 0x55555555 },
74 { DC_COM_PIN_OUTPUT_ENABLE(1), 0x55150005 },
75 { DC_COM_PIN_OUTPUT_ENABLE(0), 0x55555555 },
76};
77
78static void tegra_dc_write_regs(struct tegra_dc *dc,
79 const struct reg_entry *table,
80 unsigned int num)
81{
82 unsigned int i;
83
84 for (i = 0; i < num; i++)
85 tegra_dc_writel(dc, table[i].value, table[i].offset);
86}
87
88static int tegra_output_rgb_enable(struct tegra_output *output)
89{
90 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
91
92 tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
93
94 return 0;
95}
96
97static int tegra_output_rgb_disable(struct tegra_output *output)
98{
99 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
100
101 tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
102
103 return 0;
104}
105
106static int tegra_output_rgb_setup_clock(struct tegra_output *output,
107 struct clk *clk, unsigned long pclk)
108{
109 struct tegra_rgb *rgb = to_rgb(output);
110
111 return clk_set_parent(clk, rgb->clk_parent);
112}
113
114static int tegra_output_rgb_check_mode(struct tegra_output *output,
115 struct drm_display_mode *mode,
116 enum drm_mode_status *status)
117{
118 /*
119 * FIXME: For now, always assume that the mode is okay. There are
120 * unresolved issues with clk_round_rate(), which doesn't always
121 * reliably report whether a frequency can be set or not.
122 */
123
124 *status = MODE_OK;
125
126 return 0;
127}
128
129static const struct tegra_output_ops rgb_ops = {
130 .enable = tegra_output_rgb_enable,
131 .disable = tegra_output_rgb_disable,
132 .setup_clock = tegra_output_rgb_setup_clock,
133 .check_mode = tegra_output_rgb_check_mode,
134};
135
136int tegra_dc_rgb_probe(struct tegra_dc *dc)
137{
138 struct device_node *np;
139 struct tegra_rgb *rgb;
140 int err;
141
142 np = of_get_child_by_name(dc->dev->of_node, "rgb");
143 if (!np || !of_device_is_available(np))
144 return -ENODEV;
145
146 rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL);
147 if (!rgb)
148 return -ENOMEM;
149
150 rgb->clk = devm_clk_get(dc->dev, NULL);
151 if (IS_ERR(rgb->clk)) {
152 dev_err(dc->dev, "failed to get clock\n");
153 return PTR_ERR(rgb->clk);
154 }
155
156 rgb->clk_parent = devm_clk_get(dc->dev, "parent");
157 if (IS_ERR(rgb->clk_parent)) {
158 dev_err(dc->dev, "failed to get parent clock\n");
159 return PTR_ERR(rgb->clk_parent);
160 }
161
162 err = clk_set_parent(rgb->clk, rgb->clk_parent);
163 if (err < 0) {
164 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
165 return err;
166 }
167
168 rgb->output.dev = dc->dev;
169 rgb->output.of_node = np;
170
171 err = tegra_output_parse_dt(&rgb->output);
172 if (err < 0)
173 return err;
174
175 dc->rgb = &rgb->output;
176
177 return 0;
178}
179
180int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
181{
182 struct tegra_rgb *rgb = to_rgb(dc->rgb);
183 int err;
184
185 if (!dc->rgb)
186 return -ENODEV;
187
188 rgb->output.type = TEGRA_OUTPUT_RGB;
189 rgb->output.ops = &rgb_ops;
190
191 err = tegra_output_init(dc->base.dev, &rgb->output);
192 if (err < 0) {
193 dev_err(dc->dev, "output setup failed: %d\n", err);
194 return err;
195 }
196
197 /*
198 * By default, outputs can be associated with each display controller.
199 * RGB outputs are an exception, so we make sure they can be attached
200 * to only their parent display controller.
201 */
202 rgb->output.encoder.possible_crtcs = 1 << dc->pipe;
203
204 return 0;
205}
206
207int tegra_dc_rgb_exit(struct tegra_dc *dc)
208{
209 if (dc->rgb) {
210 int err;
211
212 err = tegra_output_disable(dc->rgb);
213 if (err < 0) {
214 dev_err(dc->dev, "output failed to disable: %d\n", err);
215 return err;
216 }
217
218 err = tegra_output_exit(dc->rgb);
219 if (err < 0) {
220 dev_err(dc->dev, "output cleanup failed: %d\n", err);
221 return err;
222 }
223
224 dc->rgb = NULL;
225 }
226
227 return 0;
228}