aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2013-10-09 04:32:49 -0400
committerThierry Reding <treding@nvidia.com>2013-10-31 04:55:40 -0400
commitdee8268f8fb218c9e9b604a40f7dbdd395e910f9 (patch)
treeb28f659398ca70881bccde1cef8c34357faf6964 /drivers/gpu/host1x
parentfc3be3e8fc8b3b6e800d6dc8ffb794e9d27ba5d2 (diff)
drm/tegra: Move driver to DRM tree
In order to make subsystem-wide changes easier, move the Tegra DRM driver back into the DRM tree. Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/host1x')
-rw-r--r--drivers/gpu/host1x/Kconfig2
-rw-r--r--drivers/gpu/host1x/Makefile8
-rw-r--r--drivers/gpu/host1x/drm/Kconfig29
-rw-r--r--drivers/gpu/host1x/drm/bus.c76
-rw-r--r--drivers/gpu/host1x/drm/dc.c1194
-rw-r--r--drivers/gpu/host1x/drm/dc.h400
-rw-r--r--drivers/gpu/host1x/drm/drm.c545
-rw-r--r--drivers/gpu/host1x/drm/drm.h258
-rw-r--r--drivers/gpu/host1x/drm/fb.c372
-rw-r--r--drivers/gpu/host1x/drm/gem.c248
-rw-r--r--drivers/gpu/host1x/drm/gem.h56
-rw-r--r--drivers/gpu/host1x/drm/gr2d.c343
-rw-r--r--drivers/gpu/host1x/drm/hdmi.c1295
-rw-r--r--drivers/gpu/host1x/drm/hdmi.h386
-rw-r--r--drivers/gpu/host1x/drm/output.c270
-rw-r--r--drivers/gpu/host1x/drm/rgb.c225
16 files changed, 0 insertions, 5707 deletions
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index ccfd42b23606..7d6bed222542 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -19,6 +19,4 @@ 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
24endif 22endif
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 616fe82ce715..889217cfb79d 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -9,12 +9,4 @@ host1x-y = \
9 debug.o \ 9 debug.o \
10 hw/host1x01.o 10 hw/host1x01.o
11 11
12ccflags-y += -Iinclude/drm
13ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
14
15host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
16host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
17host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o
18host1x-$(CONFIG_DRM_TEGRA) += drm/gr2d.o
19host1x-$(CONFIG_DRM_TEGRA) += drm/bus.o
20obj-$(CONFIG_TEGRA_HOST1X) += host1x.o 12obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig
deleted file mode 100644
index 69853a4de40a..000000000000
--- a/drivers/gpu/host1x/drm/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
1config DRM_TEGRA
2 bool "NVIDIA Tegra DRM"
3 depends on DRM
4 select DRM_KMS_HELPER
5 select FB_SYS_FILLRECT
6 select FB_SYS_COPYAREA
7 select FB_SYS_IMAGEBLIT
8 help
9 Choose this option if you have an NVIDIA Tegra SoC.
10
11 To compile this driver as a module, choose M here: the module
12 will be called tegra-drm.
13
14if DRM_TEGRA
15
16config DRM_TEGRA_STAGING
17 bool "Enable HOST1X interface"
18 depends on STAGING
19 help
20 Say yes if HOST1X should be available for userspace DRM users.
21
22 If unsure, choose N.
23
24config DRM_TEGRA_DEBUG
25 bool "NVIDIA Tegra DRM debug support"
26 help
27 Say yes here to enable debugging support.
28
29endif
diff --git a/drivers/gpu/host1x/drm/bus.c b/drivers/gpu/host1x/drm/bus.c
deleted file mode 100644
index 565f8f7b9a47..000000000000
--- a/drivers/gpu/host1x/drm/bus.c
+++ /dev/null
@@ -1,76 +0,0 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include "drm.h"
10
11static int drm_host1x_set_busid(struct drm_device *dev,
12 struct drm_master *master)
13{
14 const char *device = dev_name(dev->dev);
15 const char *driver = dev->driver->name;
16 const char *bus = dev->dev->bus->name;
17 int length;
18
19 master->unique_len = strlen(bus) + 1 + strlen(device);
20 master->unique_size = master->unique_len;
21
22 master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
23 if (!master->unique)
24 return -ENOMEM;
25
26 snprintf(master->unique, master->unique_len + 1, "%s:%s", bus, device);
27
28 length = strlen(driver) + 1 + master->unique_len;
29
30 dev->devname = kmalloc(length + 1, GFP_KERNEL);
31 if (!dev->devname)
32 return -ENOMEM;
33
34 snprintf(dev->devname, length + 1, "%s@%s", driver, master->unique);
35
36 return 0;
37}
38
39static struct drm_bus drm_host1x_bus = {
40 .bus_type = DRIVER_BUS_HOST1X,
41 .set_busid = drm_host1x_set_busid,
42};
43
44int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
45{
46 struct drm_device *drm;
47 int ret;
48
49 INIT_LIST_HEAD(&driver->device_list);
50 driver->bus = &drm_host1x_bus;
51
52 drm = drm_dev_alloc(driver, &device->dev);
53 if (!drm)
54 return -ENOMEM;
55
56 ret = drm_dev_register(drm, 0);
57 if (ret)
58 goto err_free;
59
60 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name,
61 driver->major, driver->minor, driver->patchlevel,
62 driver->date, drm->primary->index);
63
64 return 0;
65
66err_free:
67 drm_dev_free(drm);
68 return ret;
69}
70
71void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device)
72{
73 struct tegra_drm *tegra = dev_get_drvdata(&device->dev);
74
75 drm_put_dev(tegra->drm);
76}
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
deleted file mode 100644
index 588d4ba0d8cf..000000000000
--- a/drivers/gpu/host1x/drm/dc.c
+++ /dev/null
@@ -1,1194 +0,0 @@
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/clk/tegra.h>
12#include <linux/debugfs.h>
13
14#include "dc.h"
15#include "drm.h"
16#include "gem.h"
17
18struct tegra_plane {
19 struct drm_plane base;
20 unsigned int index;
21};
22
23static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
24{
25 return container_of(plane, struct tegra_plane, base);
26}
27
28static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
29 struct drm_framebuffer *fb, int crtc_x,
30 int crtc_y, unsigned int crtc_w,
31 unsigned int crtc_h, uint32_t src_x,
32 uint32_t src_y, uint32_t src_w, uint32_t src_h)
33{
34 struct tegra_plane *p = to_tegra_plane(plane);
35 struct tegra_dc *dc = to_tegra_dc(crtc);
36 struct tegra_dc_window window;
37 unsigned int i;
38
39 memset(&window, 0, sizeof(window));
40 window.src.x = src_x >> 16;
41 window.src.y = src_y >> 16;
42 window.src.w = src_w >> 16;
43 window.src.h = src_h >> 16;
44 window.dst.x = crtc_x;
45 window.dst.y = crtc_y;
46 window.dst.w = crtc_w;
47 window.dst.h = crtc_h;
48 window.format = tegra_dc_format(fb->pixel_format);
49 window.bits_per_pixel = fb->bits_per_pixel;
50
51 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
52 struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
53
54 window.base[i] = bo->paddr + fb->offsets[i];
55
56 /*
57 * Tegra doesn't support different strides for U and V planes
58 * so we display a warning if the user tries to display a
59 * framebuffer with such a configuration.
60 */
61 if (i >= 2) {
62 if (fb->pitches[i] != window.stride[1])
63 DRM_ERROR("unsupported UV-plane configuration\n");
64 } else {
65 window.stride[i] = fb->pitches[i];
66 }
67 }
68
69 return tegra_dc_setup_window(dc, p->index, &window);
70}
71
72static int tegra_plane_disable(struct drm_plane *plane)
73{
74 struct tegra_dc *dc = to_tegra_dc(plane->crtc);
75 struct tegra_plane *p = to_tegra_plane(plane);
76 unsigned long value;
77
78 if (!plane->crtc)
79 return 0;
80
81 value = WINDOW_A_SELECT << p->index;
82 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
83
84 value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
85 value &= ~WIN_ENABLE;
86 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
87
88 tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL);
89 tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL);
90
91 return 0;
92}
93
94static void tegra_plane_destroy(struct drm_plane *plane)
95{
96 tegra_plane_disable(plane);
97 drm_plane_cleanup(plane);
98}
99
100static const struct drm_plane_funcs tegra_plane_funcs = {
101 .update_plane = tegra_plane_update,
102 .disable_plane = tegra_plane_disable,
103 .destroy = tegra_plane_destroy,
104};
105
106static const uint32_t plane_formats[] = {
107 DRM_FORMAT_XBGR8888,
108 DRM_FORMAT_XRGB8888,
109 DRM_FORMAT_RGB565,
110 DRM_FORMAT_UYVY,
111 DRM_FORMAT_YUV420,
112 DRM_FORMAT_YUV422,
113};
114
115static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
116{
117 unsigned int i;
118 int err = 0;
119
120 for (i = 0; i < 2; i++) {
121 struct tegra_plane *plane;
122
123 plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
124 if (!plane)
125 return -ENOMEM;
126
127 plane->index = 1 + i;
128
129 err = drm_plane_init(drm, &plane->base, 1 << dc->pipe,
130 &tegra_plane_funcs, plane_formats,
131 ARRAY_SIZE(plane_formats), false);
132 if (err < 0)
133 return err;
134 }
135
136 return 0;
137}
138
139static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
140 struct drm_framebuffer *fb)
141{
142 unsigned int format = tegra_dc_format(fb->pixel_format);
143 struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
144 unsigned long value;
145
146 tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
147
148 value = fb->offsets[0] + y * fb->pitches[0] +
149 x * fb->bits_per_pixel / 8;
150
151 tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR);
152 tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
153 tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
154
155 value = GENERAL_UPDATE | WIN_A_UPDATE;
156 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
157
158 value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
159 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
160
161 return 0;
162}
163
164void tegra_dc_enable_vblank(struct tegra_dc *dc)
165{
166 unsigned long value, flags;
167
168 spin_lock_irqsave(&dc->lock, flags);
169
170 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
171 value |= VBLANK_INT;
172 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
173
174 spin_unlock_irqrestore(&dc->lock, flags);
175}
176
177void tegra_dc_disable_vblank(struct tegra_dc *dc)
178{
179 unsigned long value, flags;
180
181 spin_lock_irqsave(&dc->lock, flags);
182
183 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
184 value &= ~VBLANK_INT;
185 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
186
187 spin_unlock_irqrestore(&dc->lock, flags);
188}
189
190static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
191{
192 struct drm_device *drm = dc->base.dev;
193 struct drm_crtc *crtc = &dc->base;
194 unsigned long flags, base;
195 struct tegra_bo *bo;
196
197 if (!dc->event)
198 return;
199
200 bo = tegra_fb_get_plane(crtc->fb, 0);
201
202 /* check if new start address has been latched */
203 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
204 base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
205 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
206
207 if (base == bo->paddr + crtc->fb->offsets[0]) {
208 spin_lock_irqsave(&drm->event_lock, flags);
209 drm_send_vblank_event(drm, dc->pipe, dc->event);
210 drm_vblank_put(drm, dc->pipe);
211 dc->event = NULL;
212 spin_unlock_irqrestore(&drm->event_lock, flags);
213 }
214}
215
216void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
217{
218 struct tegra_dc *dc = to_tegra_dc(crtc);
219 struct drm_device *drm = crtc->dev;
220 unsigned long flags;
221
222 spin_lock_irqsave(&drm->event_lock, flags);
223
224 if (dc->event && dc->event->base.file_priv == file) {
225 dc->event->base.destroy(&dc->event->base);
226 drm_vblank_put(drm, dc->pipe);
227 dc->event = NULL;
228 }
229
230 spin_unlock_irqrestore(&drm->event_lock, flags);
231}
232
233static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
234 struct drm_pending_vblank_event *event, uint32_t page_flip_flags)
235{
236 struct tegra_dc *dc = to_tegra_dc(crtc);
237 struct drm_device *drm = crtc->dev;
238
239 if (dc->event)
240 return -EBUSY;
241
242 if (event) {
243 event->pipe = dc->pipe;
244 dc->event = event;
245 drm_vblank_get(drm, dc->pipe);
246 }
247
248 tegra_dc_set_base(dc, 0, 0, fb);
249 crtc->fb = fb;
250
251 return 0;
252}
253
254static const struct drm_crtc_funcs tegra_crtc_funcs = {
255 .page_flip = tegra_dc_page_flip,
256 .set_config = drm_crtc_helper_set_config,
257 .destroy = drm_crtc_cleanup,
258};
259
260static void tegra_crtc_disable(struct drm_crtc *crtc)
261{
262 struct drm_device *drm = crtc->dev;
263 struct drm_plane *plane;
264
265 list_for_each_entry(plane, &drm->mode_config.plane_list, head) {
266 if (plane->crtc == crtc) {
267 tegra_plane_disable(plane);
268 plane->crtc = NULL;
269
270 if (plane->fb) {
271 drm_framebuffer_unreference(plane->fb);
272 plane->fb = NULL;
273 }
274 }
275 }
276}
277
278static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
279 const struct drm_display_mode *mode,
280 struct drm_display_mode *adjusted)
281{
282 return true;
283}
284
285static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
286 unsigned int bpp)
287{
288 fixed20_12 outf = dfixed_init(out);
289 fixed20_12 inf = dfixed_init(in);
290 u32 dda_inc;
291 int max;
292
293 if (v)
294 max = 15;
295 else {
296 switch (bpp) {
297 case 2:
298 max = 8;
299 break;
300
301 default:
302 WARN_ON_ONCE(1);
303 /* fallthrough */
304 case 4:
305 max = 4;
306 break;
307 }
308 }
309
310 outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
311 inf.full -= dfixed_const(1);
312
313 dda_inc = dfixed_div(inf, outf);
314 dda_inc = min_t(u32, dda_inc, dfixed_const(max));
315
316 return dda_inc;
317}
318
319static inline u32 compute_initial_dda(unsigned int in)
320{
321 fixed20_12 inf = dfixed_init(in);
322 return dfixed_frac(inf);
323}
324
325static int tegra_dc_set_timings(struct tegra_dc *dc,
326 struct drm_display_mode *mode)
327{
328 /* TODO: For HDMI compliance, h & v ref_to_sync should be set to 1 */
329 unsigned int h_ref_to_sync = 0;
330 unsigned int v_ref_to_sync = 0;
331 unsigned long value;
332
333 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
334
335 value = (v_ref_to_sync << 16) | h_ref_to_sync;
336 tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
337
338 value = ((mode->vsync_end - mode->vsync_start) << 16) |
339 ((mode->hsync_end - mode->hsync_start) << 0);
340 tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
341
342 value = ((mode->vtotal - mode->vsync_end) << 16) |
343 ((mode->htotal - mode->hsync_end) << 0);
344 tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
345
346 value = ((mode->vsync_start - mode->vdisplay) << 16) |
347 ((mode->hsync_start - mode->hdisplay) << 0);
348 tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
349
350 value = (mode->vdisplay << 16) | mode->hdisplay;
351 tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
352
353 return 0;
354}
355
356static int tegra_crtc_setup_clk(struct drm_crtc *crtc,
357 struct drm_display_mode *mode,
358 unsigned long *div)
359{
360 unsigned long pclk = mode->clock * 1000, rate;
361 struct tegra_dc *dc = to_tegra_dc(crtc);
362 struct tegra_output *output = NULL;
363 struct drm_encoder *encoder;
364 long err;
365
366 list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head)
367 if (encoder->crtc == crtc) {
368 output = encoder_to_output(encoder);
369 break;
370 }
371
372 if (!output)
373 return -ENODEV;
374
375 /*
376 * This assumes that the display controller will divide its parent
377 * clock by 2 to generate the pixel clock.
378 */
379 err = tegra_output_setup_clock(output, dc->clk, pclk * 2);
380 if (err < 0) {
381 dev_err(dc->dev, "failed to setup clock: %ld\n", err);
382 return err;
383 }
384
385 rate = clk_get_rate(dc->clk);
386 *div = (rate * 2 / pclk) - 2;
387
388 DRM_DEBUG_KMS("rate: %lu, div: %lu\n", rate, *div);
389
390 return 0;
391}
392
393static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
394{
395 switch (format) {
396 case WIN_COLOR_DEPTH_YCbCr422:
397 case WIN_COLOR_DEPTH_YUV422:
398 if (planar)
399 *planar = false;
400
401 return true;
402
403 case WIN_COLOR_DEPTH_YCbCr420P:
404 case WIN_COLOR_DEPTH_YUV420P:
405 case WIN_COLOR_DEPTH_YCbCr422P:
406 case WIN_COLOR_DEPTH_YUV422P:
407 case WIN_COLOR_DEPTH_YCbCr422R:
408 case WIN_COLOR_DEPTH_YUV422R:
409 case WIN_COLOR_DEPTH_YCbCr422RA:
410 case WIN_COLOR_DEPTH_YUV422RA:
411 if (planar)
412 *planar = true;
413
414 return true;
415 }
416
417 return false;
418}
419
420int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
421 const struct tegra_dc_window *window)
422{
423 unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
424 unsigned long value;
425 bool yuv, planar;
426
427 /*
428 * For YUV planar modes, the number of bytes per pixel takes into
429 * account only the luma component and therefore is 1.
430 */
431 yuv = tegra_dc_format_is_yuv(window->format, &planar);
432 if (!yuv)
433 bpp = window->bits_per_pixel / 8;
434 else
435 bpp = planar ? 1 : 2;
436
437 value = WINDOW_A_SELECT << index;
438 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
439
440 tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
441 tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
442
443 value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
444 tegra_dc_writel(dc, value, DC_WIN_POSITION);
445
446 value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
447 tegra_dc_writel(dc, value, DC_WIN_SIZE);
448
449 h_offset = window->src.x * bpp;
450 v_offset = window->src.y;
451 h_size = window->src.w * bpp;
452 v_size = window->src.h;
453
454 value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
455 tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
456
457 /*
458 * For DDA computations the number of bytes per pixel for YUV planar
459 * modes needs to take into account all Y, U and V components.
460 */
461 if (yuv && planar)
462 bpp = 2;
463
464 h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
465 v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
466
467 value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
468 tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
469
470 h_dda = compute_initial_dda(window->src.x);
471 v_dda = compute_initial_dda(window->src.y);
472
473 tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
474 tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
475
476 tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
477 tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
478
479 tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
480
481 if (yuv && planar) {
482 tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
483 tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
484 value = window->stride[1] << 16 | window->stride[0];
485 tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
486 } else {
487 tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
488 }
489
490 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
491 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
492
493 value = WIN_ENABLE;
494
495 if (yuv) {
496 /* setup default colorspace conversion coefficients */
497 tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
498 tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
499 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
500 tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
501 tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
502 tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
503 tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
504 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
505
506 value |= CSC_ENABLE;
507 } else if (window->bits_per_pixel < 24) {
508 value |= COLOR_EXPAND;
509 }
510
511 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
512
513 /*
514 * Disable blending and assume Window A is the bottom-most window,
515 * Window C is the top-most window and Window B is in the middle.
516 */
517 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
518 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
519
520 switch (index) {
521 case 0:
522 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
523 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
524 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
525 break;
526
527 case 1:
528 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
529 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
530 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
531 break;
532
533 case 2:
534 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
535 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
536 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
537 break;
538 }
539
540 tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL);
541 tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL);
542
543 return 0;
544}
545
546unsigned int tegra_dc_format(uint32_t format)
547{
548 switch (format) {
549 case DRM_FORMAT_XBGR8888:
550 return WIN_COLOR_DEPTH_R8G8B8A8;
551
552 case DRM_FORMAT_XRGB8888:
553 return WIN_COLOR_DEPTH_B8G8R8A8;
554
555 case DRM_FORMAT_RGB565:
556 return WIN_COLOR_DEPTH_B5G6R5;
557
558 case DRM_FORMAT_UYVY:
559 return WIN_COLOR_DEPTH_YCbCr422;
560
561 case DRM_FORMAT_YUV420:
562 return WIN_COLOR_DEPTH_YCbCr420P;
563
564 case DRM_FORMAT_YUV422:
565 return WIN_COLOR_DEPTH_YCbCr422P;
566
567 default:
568 break;
569 }
570
571 WARN(1, "unsupported pixel format %u, using default\n", format);
572 return WIN_COLOR_DEPTH_B8G8R8A8;
573}
574
575static int tegra_crtc_mode_set(struct drm_crtc *crtc,
576 struct drm_display_mode *mode,
577 struct drm_display_mode *adjusted,
578 int x, int y, struct drm_framebuffer *old_fb)
579{
580 struct tegra_bo *bo = tegra_fb_get_plane(crtc->fb, 0);
581 struct tegra_dc *dc = to_tegra_dc(crtc);
582 struct tegra_dc_window window;
583 unsigned long div, value;
584 int err;
585
586 drm_vblank_pre_modeset(crtc->dev, dc->pipe);
587
588 err = tegra_crtc_setup_clk(crtc, mode, &div);
589 if (err) {
590 dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
591 return err;
592 }
593
594 /* program display mode */
595 tegra_dc_set_timings(dc, mode);
596
597 value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
598 tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
599
600 value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
601 value &= ~LVS_OUTPUT_POLARITY_LOW;
602 value &= ~LHS_OUTPUT_POLARITY_LOW;
603 tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
604
605 value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
606 DISP_ORDER_RED_BLUE;
607 tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
608
609 tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
610
611 value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
612 tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
613
614 /* setup window parameters */
615 memset(&window, 0, sizeof(window));
616 window.src.x = 0;
617 window.src.y = 0;
618 window.src.w = mode->hdisplay;
619 window.src.h = mode->vdisplay;
620 window.dst.x = 0;
621 window.dst.y = 0;
622 window.dst.w = mode->hdisplay;
623 window.dst.h = mode->vdisplay;
624 window.format = tegra_dc_format(crtc->fb->pixel_format);
625 window.bits_per_pixel = crtc->fb->bits_per_pixel;
626 window.stride[0] = crtc->fb->pitches[0];
627 window.base[0] = bo->paddr;
628
629 err = tegra_dc_setup_window(dc, 0, &window);
630 if (err < 0)
631 dev_err(dc->dev, "failed to enable root plane\n");
632
633 return 0;
634}
635
636static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
637 struct drm_framebuffer *old_fb)
638{
639 struct tegra_dc *dc = to_tegra_dc(crtc);
640
641 return tegra_dc_set_base(dc, x, y, crtc->fb);
642}
643
644static void tegra_crtc_prepare(struct drm_crtc *crtc)
645{
646 struct tegra_dc *dc = to_tegra_dc(crtc);
647 unsigned int syncpt;
648 unsigned long value;
649
650 /* hardware initialization */
651 tegra_periph_reset_deassert(dc->clk);
652 usleep_range(10000, 20000);
653
654 if (dc->pipe)
655 syncpt = SYNCPT_VBLANK1;
656 else
657 syncpt = SYNCPT_VBLANK0;
658
659 /* initialize display controller */
660 tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
661 tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
662
663 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
664 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
665
666 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
667 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
668 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
669
670 value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
671 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
672 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
673
674 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
675 value |= DISP_CTRL_MODE_C_DISPLAY;
676 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
677
678 /* initialize timer */
679 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
680 WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
681 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
682
683 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
684 WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
685 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
686
687 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
688 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
689
690 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
691 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
692}
693
694static void tegra_crtc_commit(struct drm_crtc *crtc)
695{
696 struct tegra_dc *dc = to_tegra_dc(crtc);
697 unsigned long value;
698
699 value = GENERAL_UPDATE | WIN_A_UPDATE;
700 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
701
702 value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
703 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
704
705 drm_vblank_post_modeset(crtc->dev, dc->pipe);
706}
707
708static void tegra_crtc_load_lut(struct drm_crtc *crtc)
709{
710}
711
712static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
713 .disable = tegra_crtc_disable,
714 .mode_fixup = tegra_crtc_mode_fixup,
715 .mode_set = tegra_crtc_mode_set,
716 .mode_set_base = tegra_crtc_mode_set_base,
717 .prepare = tegra_crtc_prepare,
718 .commit = tegra_crtc_commit,
719 .load_lut = tegra_crtc_load_lut,
720};
721
722static irqreturn_t tegra_dc_irq(int irq, void *data)
723{
724 struct tegra_dc *dc = data;
725 unsigned long status;
726
727 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
728 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
729
730 if (status & FRAME_END_INT) {
731 /*
732 dev_dbg(dc->dev, "%s(): frame end\n", __func__);
733 */
734 }
735
736 if (status & VBLANK_INT) {
737 /*
738 dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
739 */
740 drm_handle_vblank(dc->base.dev, dc->pipe);
741 tegra_dc_finish_page_flip(dc);
742 }
743
744 if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
745 /*
746 dev_dbg(dc->dev, "%s(): underflow\n", __func__);
747 */
748 }
749
750 return IRQ_HANDLED;
751}
752
753static int tegra_dc_show_regs(struct seq_file *s, void *data)
754{
755 struct drm_info_node *node = s->private;
756 struct tegra_dc *dc = node->info_ent->data;
757
758#define DUMP_REG(name) \
759 seq_printf(s, "%-40s %#05x %08lx\n", #name, name, \
760 tegra_dc_readl(dc, name))
761
762 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT);
763 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
764 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR);
765 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT);
766 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL);
767 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR);
768 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT);
769 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL);
770 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR);
771 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT);
772 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL);
773 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR);
774 DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC);
775 DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
776 DUMP_REG(DC_CMD_DISPLAY_COMMAND);
777 DUMP_REG(DC_CMD_SIGNAL_RAISE);
778 DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
779 DUMP_REG(DC_CMD_INT_STATUS);
780 DUMP_REG(DC_CMD_INT_MASK);
781 DUMP_REG(DC_CMD_INT_ENABLE);
782 DUMP_REG(DC_CMD_INT_TYPE);
783 DUMP_REG(DC_CMD_INT_POLARITY);
784 DUMP_REG(DC_CMD_SIGNAL_RAISE1);
785 DUMP_REG(DC_CMD_SIGNAL_RAISE2);
786 DUMP_REG(DC_CMD_SIGNAL_RAISE3);
787 DUMP_REG(DC_CMD_STATE_ACCESS);
788 DUMP_REG(DC_CMD_STATE_CONTROL);
789 DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
790 DUMP_REG(DC_CMD_REG_ACT_CONTROL);
791 DUMP_REG(DC_COM_CRC_CONTROL);
792 DUMP_REG(DC_COM_CRC_CHECKSUM);
793 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0));
794 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1));
795 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2));
796 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3));
797 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0));
798 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1));
799 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2));
800 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3));
801 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0));
802 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1));
803 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2));
804 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3));
805 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0));
806 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1));
807 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2));
808 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3));
809 DUMP_REG(DC_COM_PIN_INPUT_DATA(0));
810 DUMP_REG(DC_COM_PIN_INPUT_DATA(1));
811 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0));
812 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1));
813 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2));
814 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3));
815 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4));
816 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5));
817 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6));
818 DUMP_REG(DC_COM_PIN_MISC_CONTROL);
819 DUMP_REG(DC_COM_PIN_PM0_CONTROL);
820 DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE);
821 DUMP_REG(DC_COM_PIN_PM1_CONTROL);
822 DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE);
823 DUMP_REG(DC_COM_SPI_CONTROL);
824 DUMP_REG(DC_COM_SPI_START_BYTE);
825 DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB);
826 DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD);
827 DUMP_REG(DC_COM_HSPI_CS_DC);
828 DUMP_REG(DC_COM_SCRATCH_REGISTER_A);
829 DUMP_REG(DC_COM_SCRATCH_REGISTER_B);
830 DUMP_REG(DC_COM_GPIO_CTRL);
831 DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER);
832 DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED);
833 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
834 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
835 DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
836 DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY);
837 DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
838 DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
839 DUMP_REG(DC_DISP_REF_TO_SYNC);
840 DUMP_REG(DC_DISP_SYNC_WIDTH);
841 DUMP_REG(DC_DISP_BACK_PORCH);
842 DUMP_REG(DC_DISP_ACTIVE);
843 DUMP_REG(DC_DISP_FRONT_PORCH);
844 DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
845 DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
846 DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
847 DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
848 DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
849 DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
850 DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
851 DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
852 DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
853 DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
854 DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
855 DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
856 DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
857 DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
858 DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
859 DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
860 DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
861 DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
862 DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
863 DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
864 DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
865 DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
866 DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
867 DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
868 DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
869 DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
870 DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
871 DUMP_REG(DC_DISP_M0_CONTROL);
872 DUMP_REG(DC_DISP_M1_CONTROL);
873 DUMP_REG(DC_DISP_DI_CONTROL);
874 DUMP_REG(DC_DISP_PP_CONTROL);
875 DUMP_REG(DC_DISP_PP_SELECT_A);
876 DUMP_REG(DC_DISP_PP_SELECT_B);
877 DUMP_REG(DC_DISP_PP_SELECT_C);
878 DUMP_REG(DC_DISP_PP_SELECT_D);
879 DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
880 DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
881 DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
882 DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
883 DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
884 DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
885 DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
886 DUMP_REG(DC_DISP_BORDER_COLOR);
887 DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
888 DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
889 DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
890 DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
891 DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
892 DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
893 DUMP_REG(DC_DISP_CURSOR_START_ADDR);
894 DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
895 DUMP_REG(DC_DISP_CURSOR_POSITION);
896 DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
897 DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
898 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
899 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
900 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
901 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
902 DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
903 DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
904 DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
905 DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST);
906 DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
907 DUMP_REG(DC_DISP_DAC_CRT_CTRL);
908 DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
909 DUMP_REG(DC_DISP_SD_CONTROL);
910 DUMP_REG(DC_DISP_SD_CSC_COEFF);
911 DUMP_REG(DC_DISP_SD_LUT(0));
912 DUMP_REG(DC_DISP_SD_LUT(1));
913 DUMP_REG(DC_DISP_SD_LUT(2));
914 DUMP_REG(DC_DISP_SD_LUT(3));
915 DUMP_REG(DC_DISP_SD_LUT(4));
916 DUMP_REG(DC_DISP_SD_LUT(5));
917 DUMP_REG(DC_DISP_SD_LUT(6));
918 DUMP_REG(DC_DISP_SD_LUT(7));
919 DUMP_REG(DC_DISP_SD_LUT(8));
920 DUMP_REG(DC_DISP_SD_FLICKER_CONTROL);
921 DUMP_REG(DC_DISP_DC_PIXEL_COUNT);
922 DUMP_REG(DC_DISP_SD_HISTOGRAM(0));
923 DUMP_REG(DC_DISP_SD_HISTOGRAM(1));
924 DUMP_REG(DC_DISP_SD_HISTOGRAM(2));
925 DUMP_REG(DC_DISP_SD_HISTOGRAM(3));
926 DUMP_REG(DC_DISP_SD_HISTOGRAM(4));
927 DUMP_REG(DC_DISP_SD_HISTOGRAM(5));
928 DUMP_REG(DC_DISP_SD_HISTOGRAM(6));
929 DUMP_REG(DC_DISP_SD_HISTOGRAM(7));
930 DUMP_REG(DC_DISP_SD_BL_TF(0));
931 DUMP_REG(DC_DISP_SD_BL_TF(1));
932 DUMP_REG(DC_DISP_SD_BL_TF(2));
933 DUMP_REG(DC_DISP_SD_BL_TF(3));
934 DUMP_REG(DC_DISP_SD_BL_CONTROL);
935 DUMP_REG(DC_DISP_SD_HW_K_VALUES);
936 DUMP_REG(DC_DISP_SD_MAN_K_VALUES);
937 DUMP_REG(DC_WIN_WIN_OPTIONS);
938 DUMP_REG(DC_WIN_BYTE_SWAP);
939 DUMP_REG(DC_WIN_BUFFER_CONTROL);
940 DUMP_REG(DC_WIN_COLOR_DEPTH);
941 DUMP_REG(DC_WIN_POSITION);
942 DUMP_REG(DC_WIN_SIZE);
943 DUMP_REG(DC_WIN_PRESCALED_SIZE);
944 DUMP_REG(DC_WIN_H_INITIAL_DDA);
945 DUMP_REG(DC_WIN_V_INITIAL_DDA);
946 DUMP_REG(DC_WIN_DDA_INC);
947 DUMP_REG(DC_WIN_LINE_STRIDE);
948 DUMP_REG(DC_WIN_BUF_STRIDE);
949 DUMP_REG(DC_WIN_UV_BUF_STRIDE);
950 DUMP_REG(DC_WIN_BUFFER_ADDR_MODE);
951 DUMP_REG(DC_WIN_DV_CONTROL);
952 DUMP_REG(DC_WIN_BLEND_NOKEY);
953 DUMP_REG(DC_WIN_BLEND_1WIN);
954 DUMP_REG(DC_WIN_BLEND_2WIN_X);
955 DUMP_REG(DC_WIN_BLEND_2WIN_Y);
956 DUMP_REG(DC_WIN_BLEND_3WIN_XY);
957 DUMP_REG(DC_WIN_HP_FETCH_CONTROL);
958 DUMP_REG(DC_WINBUF_START_ADDR);
959 DUMP_REG(DC_WINBUF_START_ADDR_NS);
960 DUMP_REG(DC_WINBUF_START_ADDR_U);
961 DUMP_REG(DC_WINBUF_START_ADDR_U_NS);
962 DUMP_REG(DC_WINBUF_START_ADDR_V);
963 DUMP_REG(DC_WINBUF_START_ADDR_V_NS);
964 DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
965 DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS);
966 DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
967 DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS);
968 DUMP_REG(DC_WINBUF_UFLOW_STATUS);
969 DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS);
970 DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS);
971 DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS);
972
973#undef DUMP_REG
974
975 return 0;
976}
977
978static struct drm_info_list debugfs_files[] = {
979 { "regs", tegra_dc_show_regs, 0, NULL },
980};
981
982static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
983{
984 unsigned int i;
985 char *name;
986 int err;
987
988 name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
989 dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
990 kfree(name);
991
992 if (!dc->debugfs)
993 return -ENOMEM;
994
995 dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
996 GFP_KERNEL);
997 if (!dc->debugfs_files) {
998 err = -ENOMEM;
999 goto remove;
1000 }
1001
1002 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1003 dc->debugfs_files[i].data = dc;
1004
1005 err = drm_debugfs_create_files(dc->debugfs_files,
1006 ARRAY_SIZE(debugfs_files),
1007 dc->debugfs, minor);
1008 if (err < 0)
1009 goto free;
1010
1011 dc->minor = minor;
1012
1013 return 0;
1014
1015free:
1016 kfree(dc->debugfs_files);
1017 dc->debugfs_files = NULL;
1018remove:
1019 debugfs_remove(dc->debugfs);
1020 dc->debugfs = NULL;
1021
1022 return err;
1023}
1024
1025static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
1026{
1027 drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
1028 dc->minor);
1029 dc->minor = NULL;
1030
1031 kfree(dc->debugfs_files);
1032 dc->debugfs_files = NULL;
1033
1034 debugfs_remove(dc->debugfs);
1035 dc->debugfs = NULL;
1036
1037 return 0;
1038}
1039
1040static int tegra_dc_init(struct host1x_client *client)
1041{
1042 struct tegra_drm *tegra = dev_get_drvdata(client->parent);
1043 struct tegra_dc *dc = host1x_client_to_dc(client);
1044 int err;
1045
1046 dc->pipe = tegra->drm->mode_config.num_crtc;
1047
1048 drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
1049 drm_mode_crtc_set_gamma_size(&dc->base, 256);
1050 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1051
1052 err = tegra_dc_rgb_init(tegra->drm, dc);
1053 if (err < 0 && err != -ENODEV) {
1054 dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
1055 return err;
1056 }
1057
1058 err = tegra_dc_add_planes(tegra->drm, dc);
1059 if (err < 0)
1060 return err;
1061
1062 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1063 err = tegra_dc_debugfs_init(dc, tegra->drm->primary);
1064 if (err < 0)
1065 dev_err(dc->dev, "debugfs setup failed: %d\n", err);
1066 }
1067
1068 err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
1069 dev_name(dc->dev), dc);
1070 if (err < 0) {
1071 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
1072 err);
1073 return err;
1074 }
1075
1076 return 0;
1077}
1078
1079static int tegra_dc_exit(struct host1x_client *client)
1080{
1081 struct tegra_dc *dc = host1x_client_to_dc(client);
1082 int err;
1083
1084 devm_free_irq(dc->dev, dc->irq, dc);
1085
1086 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1087 err = tegra_dc_debugfs_exit(dc);
1088 if (err < 0)
1089 dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
1090 }
1091
1092 err = tegra_dc_rgb_exit(dc);
1093 if (err) {
1094 dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
1095 return err;
1096 }
1097
1098 return 0;
1099}
1100
1101static const struct host1x_client_ops dc_client_ops = {
1102 .init = tegra_dc_init,
1103 .exit = tegra_dc_exit,
1104};
1105
1106static int tegra_dc_probe(struct platform_device *pdev)
1107{
1108 struct resource *regs;
1109 struct tegra_dc *dc;
1110 int err;
1111
1112 dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
1113 if (!dc)
1114 return -ENOMEM;
1115
1116 spin_lock_init(&dc->lock);
1117 INIT_LIST_HEAD(&dc->list);
1118 dc->dev = &pdev->dev;
1119
1120 dc->clk = devm_clk_get(&pdev->dev, NULL);
1121 if (IS_ERR(dc->clk)) {
1122 dev_err(&pdev->dev, "failed to get clock\n");
1123 return PTR_ERR(dc->clk);
1124 }
1125
1126 err = clk_prepare_enable(dc->clk);
1127 if (err < 0)
1128 return err;
1129
1130 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1131 dc->regs = devm_ioremap_resource(&pdev->dev, regs);
1132 if (IS_ERR(dc->regs))
1133 return PTR_ERR(dc->regs);
1134
1135 dc->irq = platform_get_irq(pdev, 0);
1136 if (dc->irq < 0) {
1137 dev_err(&pdev->dev, "failed to get IRQ\n");
1138 return -ENXIO;
1139 }
1140
1141 INIT_LIST_HEAD(&dc->client.list);
1142 dc->client.ops = &dc_client_ops;
1143 dc->client.dev = &pdev->dev;
1144
1145 err = tegra_dc_rgb_probe(dc);
1146 if (err < 0 && err != -ENODEV) {
1147 dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
1148 return err;
1149 }
1150
1151 err = host1x_client_register(&dc->client);
1152 if (err < 0) {
1153 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1154 err);
1155 return err;
1156 }
1157
1158 platform_set_drvdata(pdev, dc);
1159
1160 return 0;
1161}
1162
1163static int tegra_dc_remove(struct platform_device *pdev)
1164{
1165 struct tegra_dc *dc = platform_get_drvdata(pdev);
1166 int err;
1167
1168 err = host1x_client_unregister(&dc->client);
1169 if (err < 0) {
1170 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1171 err);
1172 return err;
1173 }
1174
1175 clk_disable_unprepare(dc->clk);
1176
1177 return 0;
1178}
1179
1180static struct of_device_id tegra_dc_of_match[] = {
1181 { .compatible = "nvidia,tegra30-dc", },
1182 { .compatible = "nvidia,tegra20-dc", },
1183 { },
1184};
1185
1186struct platform_driver tegra_dc_driver = {
1187 .driver = {
1188 .name = "tegra-dc",
1189 .owner = THIS_MODULE,
1190 .of_match_table = tegra_dc_of_match,
1191 },
1192 .probe = tegra_dc_probe,
1193 .remove = tegra_dc_remove,
1194};
diff --git a/drivers/gpu/host1x/drm/dc.h b/drivers/gpu/host1x/drm/dc.h
deleted file mode 100644
index 79eaec9aac77..000000000000
--- a/drivers/gpu/host1x/drm/dc.h
+++ /dev/null
@@ -1,400 +0,0 @@
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
deleted file mode 100644
index c2db409bbd63..000000000000
--- a/drivers/gpu/host1x/drm/drm.c
+++ /dev/null
@@ -1,545 +0,0 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012-2013 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/host1x.h>
11
12#include "drm.h"
13#include "gem.h"
14
15#define DRIVER_NAME "tegra"
16#define DRIVER_DESC "NVIDIA Tegra graphics"
17#define DRIVER_DATE "20120330"
18#define DRIVER_MAJOR 0
19#define DRIVER_MINOR 0
20#define DRIVER_PATCHLEVEL 0
21
22struct tegra_drm_file {
23 struct list_head contexts;
24};
25
26static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
27{
28 struct host1x_device *device = to_host1x_device(drm->dev);
29 struct tegra_drm *tegra;
30 int err;
31
32 tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
33 if (!tegra)
34 return -ENOMEM;
35
36 dev_set_drvdata(drm->dev, tegra);
37 mutex_init(&tegra->clients_lock);
38 INIT_LIST_HEAD(&tegra->clients);
39 drm->dev_private = tegra;
40 tegra->drm = drm;
41
42 drm_mode_config_init(drm);
43
44 err = host1x_device_init(device);
45 if (err < 0)
46 return err;
47
48 /*
49 * We don't use the drm_irq_install() helpers provided by the DRM
50 * core, so we need to set this manually in order to allow the
51 * DRM_IOCTL_WAIT_VBLANK to operate correctly.
52 */
53 drm->irq_enabled = true;
54
55 err = drm_vblank_init(drm, drm->mode_config.num_crtc);
56 if (err < 0)
57 return err;
58
59 err = tegra_drm_fb_init(drm);
60 if (err < 0)
61 return err;
62
63 drm_kms_helper_poll_init(drm);
64
65 return 0;
66}
67
68static int tegra_drm_unload(struct drm_device *drm)
69{
70 struct host1x_device *device = to_host1x_device(drm->dev);
71 int err;
72
73 drm_kms_helper_poll_fini(drm);
74 tegra_drm_fb_exit(drm);
75
76 err = host1x_device_exit(device);
77 if (err < 0)
78 return err;
79
80 drm_mode_config_cleanup(drm);
81
82 return 0;
83}
84
85static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
86{
87 struct tegra_drm_file *fpriv;
88
89 fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
90 if (!fpriv)
91 return -ENOMEM;
92
93 INIT_LIST_HEAD(&fpriv->contexts);
94 filp->driver_priv = fpriv;
95
96 return 0;
97}
98
99static void tegra_drm_context_free(struct tegra_drm_context *context)
100{
101 context->client->ops->close_channel(context);
102 kfree(context);
103}
104
105static void tegra_drm_lastclose(struct drm_device *drm)
106{
107 struct tegra_drm *tegra = drm->dev_private;
108
109 tegra_fbdev_restore_mode(tegra->fbdev);
110}
111
112#ifdef CONFIG_DRM_TEGRA_STAGING
113static struct tegra_drm_context *tegra_drm_get_context(__u64 context)
114{
115 return (struct tegra_drm_context *)(uintptr_t)context;
116}
117
118static bool tegra_drm_file_owns_context(struct tegra_drm_file *file,
119 struct tegra_drm_context *context)
120{
121 struct tegra_drm_context *ctx;
122
123 list_for_each_entry(ctx, &file->contexts, list)
124 if (ctx == context)
125 return true;
126
127 return false;
128}
129
130static int tegra_gem_create(struct drm_device *drm, void *data,
131 struct drm_file *file)
132{
133 struct drm_tegra_gem_create *args = data;
134 struct tegra_bo *bo;
135
136 bo = tegra_bo_create_with_handle(file, drm, args->size,
137 &args->handle);
138 if (IS_ERR(bo))
139 return PTR_ERR(bo);
140
141 return 0;
142}
143
144static int tegra_gem_mmap(struct drm_device *drm, void *data,
145 struct drm_file *file)
146{
147 struct drm_tegra_gem_mmap *args = data;
148 struct drm_gem_object *gem;
149 struct tegra_bo *bo;
150
151 gem = drm_gem_object_lookup(drm, file, args->handle);
152 if (!gem)
153 return -EINVAL;
154
155 bo = to_tegra_bo(gem);
156
157 args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
158
159 drm_gem_object_unreference(gem);
160
161 return 0;
162}
163
164static int tegra_syncpt_read(struct drm_device *drm, void *data,
165 struct drm_file *file)
166{
167 struct host1x *host = dev_get_drvdata(drm->dev->parent);
168 struct drm_tegra_syncpt_read *args = data;
169 struct host1x_syncpt *sp;
170
171 sp = host1x_syncpt_get(host, args->id);
172 if (!sp)
173 return -EINVAL;
174
175 args->value = host1x_syncpt_read_min(sp);
176 return 0;
177}
178
179static int tegra_syncpt_incr(struct drm_device *drm, void *data,
180 struct drm_file *file)
181{
182 struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
183 struct drm_tegra_syncpt_incr *args = data;
184 struct host1x_syncpt *sp;
185
186 sp = host1x_syncpt_get(host1x, args->id);
187 if (!sp)
188 return -EINVAL;
189
190 return host1x_syncpt_incr(sp);
191}
192
193static int tegra_syncpt_wait(struct drm_device *drm, void *data,
194 struct drm_file *file)
195{
196 struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
197 struct drm_tegra_syncpt_wait *args = data;
198 struct host1x_syncpt *sp;
199
200 sp = host1x_syncpt_get(host1x, args->id);
201 if (!sp)
202 return -EINVAL;
203
204 return host1x_syncpt_wait(sp, args->thresh, args->timeout,
205 &args->value);
206}
207
208static int tegra_open_channel(struct drm_device *drm, void *data,
209 struct drm_file *file)
210{
211 struct tegra_drm_file *fpriv = file->driver_priv;
212 struct tegra_drm *tegra = drm->dev_private;
213 struct drm_tegra_open_channel *args = data;
214 struct tegra_drm_context *context;
215 struct tegra_drm_client *client;
216 int err = -ENODEV;
217
218 context = kzalloc(sizeof(*context), GFP_KERNEL);
219 if (!context)
220 return -ENOMEM;
221
222 list_for_each_entry(client, &tegra->clients, list)
223 if (client->base.class == args->client) {
224 err = client->ops->open_channel(client, context);
225 if (err)
226 break;
227
228 list_add(&context->list, &fpriv->contexts);
229 args->context = (uintptr_t)context;
230 context->client = client;
231 return 0;
232 }
233
234 kfree(context);
235 return err;
236}
237
238static int tegra_close_channel(struct drm_device *drm, void *data,
239 struct drm_file *file)
240{
241 struct tegra_drm_file *fpriv = file->driver_priv;
242 struct drm_tegra_close_channel *args = data;
243 struct tegra_drm_context *context;
244
245 context = tegra_drm_get_context(args->context);
246
247 if (!tegra_drm_file_owns_context(fpriv, context))
248 return -EINVAL;
249
250 list_del(&context->list);
251 tegra_drm_context_free(context);
252
253 return 0;
254}
255
256static int tegra_get_syncpt(struct drm_device *drm, void *data,
257 struct drm_file *file)
258{
259 struct tegra_drm_file *fpriv = file->driver_priv;
260 struct drm_tegra_get_syncpt *args = data;
261 struct tegra_drm_context *context;
262 struct host1x_syncpt *syncpt;
263
264 context = tegra_drm_get_context(args->context);
265
266 if (!tegra_drm_file_owns_context(fpriv, context))
267 return -ENODEV;
268
269 if (args->index >= context->client->base.num_syncpts)
270 return -EINVAL;
271
272 syncpt = context->client->base.syncpts[args->index];
273 args->id = host1x_syncpt_id(syncpt);
274
275 return 0;
276}
277
278static int tegra_submit(struct drm_device *drm, void *data,
279 struct drm_file *file)
280{
281 struct tegra_drm_file *fpriv = file->driver_priv;
282 struct drm_tegra_submit *args = data;
283 struct tegra_drm_context *context;
284
285 context = tegra_drm_get_context(args->context);
286
287 if (!tegra_drm_file_owns_context(fpriv, context))
288 return -ENODEV;
289
290 return context->client->ops->submit(context, args, drm, file);
291}
292#endif
293
294static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
295#ifdef CONFIG_DRM_TEGRA_STAGING
296 DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
297 DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
298 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
299 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
300 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, DRM_UNLOCKED),
301 DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, DRM_UNLOCKED),
302 DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, DRM_UNLOCKED),
303 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
304 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
305#endif
306};
307
308static const struct file_operations tegra_drm_fops = {
309 .owner = THIS_MODULE,
310 .open = drm_open,
311 .release = drm_release,
312 .unlocked_ioctl = drm_ioctl,
313 .mmap = tegra_drm_mmap,
314 .poll = drm_poll,
315 .read = drm_read,
316#ifdef CONFIG_COMPAT
317 .compat_ioctl = drm_compat_ioctl,
318#endif
319 .llseek = noop_llseek,
320};
321
322static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe)
323{
324 struct drm_crtc *crtc;
325
326 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) {
327 struct tegra_dc *dc = to_tegra_dc(crtc);
328
329 if (dc->pipe == pipe)
330 return crtc;
331 }
332
333 return NULL;
334}
335
336static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc)
337{
338 /* TODO: implement real hardware counter using syncpoints */
339 return drm_vblank_count(dev, crtc);
340}
341
342static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
343{
344 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
345 struct tegra_dc *dc = to_tegra_dc(crtc);
346
347 if (!crtc)
348 return -ENODEV;
349
350 tegra_dc_enable_vblank(dc);
351
352 return 0;
353}
354
355static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
356{
357 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
358 struct tegra_dc *dc = to_tegra_dc(crtc);
359
360 if (crtc)
361 tegra_dc_disable_vblank(dc);
362}
363
364static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
365{
366 struct tegra_drm_file *fpriv = file->driver_priv;
367 struct tegra_drm_context *context, *tmp;
368 struct drm_crtc *crtc;
369
370 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
371 tegra_dc_cancel_page_flip(crtc, file);
372
373 list_for_each_entry_safe(context, tmp, &fpriv->contexts, list)
374 tegra_drm_context_free(context);
375
376 kfree(fpriv);
377}
378
379#ifdef CONFIG_DEBUG_FS
380static int tegra_debugfs_framebuffers(struct seq_file *s, void *data)
381{
382 struct drm_info_node *node = (struct drm_info_node *)s->private;
383 struct drm_device *drm = node->minor->dev;
384 struct drm_framebuffer *fb;
385
386 mutex_lock(&drm->mode_config.fb_lock);
387
388 list_for_each_entry(fb, &drm->mode_config.fb_list, head) {
389 seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
390 fb->base.id, fb->width, fb->height, fb->depth,
391 fb->bits_per_pixel,
392 atomic_read(&fb->refcount.refcount));
393 }
394
395 mutex_unlock(&drm->mode_config.fb_lock);
396
397 return 0;
398}
399
400static struct drm_info_list tegra_debugfs_list[] = {
401 { "framebuffers", tegra_debugfs_framebuffers, 0 },
402};
403
404static int tegra_debugfs_init(struct drm_minor *minor)
405{
406 return drm_debugfs_create_files(tegra_debugfs_list,
407 ARRAY_SIZE(tegra_debugfs_list),
408 minor->debugfs_root, minor);
409}
410
411static void tegra_debugfs_cleanup(struct drm_minor *minor)
412{
413 drm_debugfs_remove_files(tegra_debugfs_list,
414 ARRAY_SIZE(tegra_debugfs_list), minor);
415}
416#endif
417
418struct drm_driver tegra_drm_driver = {
419 .driver_features = DRIVER_MODESET | DRIVER_GEM,
420 .load = tegra_drm_load,
421 .unload = tegra_drm_unload,
422 .open = tegra_drm_open,
423 .preclose = tegra_drm_preclose,
424 .lastclose = tegra_drm_lastclose,
425
426 .get_vblank_counter = tegra_drm_get_vblank_counter,
427 .enable_vblank = tegra_drm_enable_vblank,
428 .disable_vblank = tegra_drm_disable_vblank,
429
430#if defined(CONFIG_DEBUG_FS)
431 .debugfs_init = tegra_debugfs_init,
432 .debugfs_cleanup = tegra_debugfs_cleanup,
433#endif
434
435 .gem_free_object = tegra_bo_free_object,
436 .gem_vm_ops = &tegra_bo_vm_ops,
437 .dumb_create = tegra_bo_dumb_create,
438 .dumb_map_offset = tegra_bo_dumb_map_offset,
439 .dumb_destroy = drm_gem_dumb_destroy,
440
441 .ioctls = tegra_drm_ioctls,
442 .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
443 .fops = &tegra_drm_fops,
444
445 .name = DRIVER_NAME,
446 .desc = DRIVER_DESC,
447 .date = DRIVER_DATE,
448 .major = DRIVER_MAJOR,
449 .minor = DRIVER_MINOR,
450 .patchlevel = DRIVER_PATCHLEVEL,
451};
452
453int tegra_drm_register_client(struct tegra_drm *tegra,
454 struct tegra_drm_client *client)
455{
456 mutex_lock(&tegra->clients_lock);
457 list_add_tail(&client->list, &tegra->clients);
458 mutex_unlock(&tegra->clients_lock);
459
460 return 0;
461}
462
463int tegra_drm_unregister_client(struct tegra_drm *tegra,
464 struct tegra_drm_client *client)
465{
466 mutex_lock(&tegra->clients_lock);
467 list_del_init(&client->list);
468 mutex_unlock(&tegra->clients_lock);
469
470 return 0;
471}
472
473static int host1x_drm_probe(struct host1x_device *device)
474{
475 return drm_host1x_init(&tegra_drm_driver, device);
476}
477
478static int host1x_drm_remove(struct host1x_device *device)
479{
480 drm_host1x_exit(&tegra_drm_driver, device);
481
482 return 0;
483}
484
485static const struct of_device_id host1x_drm_subdevs[] = {
486 { .compatible = "nvidia,tegra20-dc", },
487 { .compatible = "nvidia,tegra20-hdmi", },
488 { .compatible = "nvidia,tegra20-gr2d", },
489 { .compatible = "nvidia,tegra30-dc", },
490 { .compatible = "nvidia,tegra30-hdmi", },
491 { .compatible = "nvidia,tegra30-gr2d", },
492 { /* sentinel */ }
493};
494
495static struct host1x_driver host1x_drm_driver = {
496 .name = "drm",
497 .probe = host1x_drm_probe,
498 .remove = host1x_drm_remove,
499 .subdevs = host1x_drm_subdevs,
500};
501
502static int __init host1x_drm_init(void)
503{
504 int err;
505
506 err = host1x_driver_register(&host1x_drm_driver);
507 if (err < 0)
508 return err;
509
510 err = platform_driver_register(&tegra_dc_driver);
511 if (err < 0)
512 goto unregister_host1x;
513
514 err = platform_driver_register(&tegra_hdmi_driver);
515 if (err < 0)
516 goto unregister_dc;
517
518 err = platform_driver_register(&tegra_gr2d_driver);
519 if (err < 0)
520 goto unregister_hdmi;
521
522 return 0;
523
524unregister_hdmi:
525 platform_driver_unregister(&tegra_hdmi_driver);
526unregister_dc:
527 platform_driver_unregister(&tegra_dc_driver);
528unregister_host1x:
529 host1x_driver_unregister(&host1x_drm_driver);
530 return err;
531}
532module_init(host1x_drm_init);
533
534static void __exit host1x_drm_exit(void)
535{
536 platform_driver_unregister(&tegra_gr2d_driver);
537 platform_driver_unregister(&tegra_hdmi_driver);
538 platform_driver_unregister(&tegra_dc_driver);
539 host1x_driver_unregister(&host1x_drm_driver);
540}
541module_exit(host1x_drm_exit);
542
543MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
544MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
545MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
deleted file mode 100644
index 25522e23c7b8..000000000000
--- a/drivers/gpu/host1x/drm/drm.h
+++ /dev/null
@@ -1,258 +0,0 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012-2013 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 <uapi/drm/tegra_drm.h>
14#include <linux/host1x.h>
15
16#include <drm/drmP.h>
17#include <drm/drm_crtc_helper.h>
18#include <drm/drm_edid.h>
19#include <drm/drm_fb_helper.h>
20#include <drm/drm_fixed.h>
21
22struct tegra_fb {
23 struct drm_framebuffer base;
24 struct tegra_bo **planes;
25 unsigned int num_planes;
26};
27
28struct tegra_fbdev {
29 struct drm_fb_helper base;
30 struct tegra_fb *fb;
31};
32
33struct tegra_drm {
34 struct drm_device *drm;
35
36 struct mutex clients_lock;
37 struct list_head clients;
38
39 struct tegra_fbdev *fbdev;
40};
41
42struct tegra_drm_client;
43
44struct tegra_drm_context {
45 struct tegra_drm_client *client;
46 struct host1x_channel *channel;
47 struct list_head list;
48};
49
50struct tegra_drm_client_ops {
51 int (*open_channel)(struct tegra_drm_client *client,
52 struct tegra_drm_context *context);
53 void (*close_channel)(struct tegra_drm_context *context);
54 int (*submit)(struct tegra_drm_context *context,
55 struct drm_tegra_submit *args, struct drm_device *drm,
56 struct drm_file *file);
57};
58
59struct tegra_drm_client {
60 struct host1x_client base;
61 struct list_head list;
62
63 const struct tegra_drm_client_ops *ops;
64};
65
66static inline struct tegra_drm_client *
67host1x_to_drm_client(struct host1x_client *client)
68{
69 return container_of(client, struct tegra_drm_client, base);
70}
71
72extern int tegra_drm_register_client(struct tegra_drm *tegra,
73 struct tegra_drm_client *client);
74extern int tegra_drm_unregister_client(struct tegra_drm *tegra,
75 struct tegra_drm_client *client);
76
77extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
78extern int tegra_drm_exit(struct tegra_drm *tegra);
79
80struct tegra_output;
81
82struct tegra_dc {
83 struct host1x_client client;
84 struct device *dev;
85 spinlock_t lock;
86
87 struct drm_crtc base;
88 int pipe;
89
90 struct clk *clk;
91 void __iomem *regs;
92 int irq;
93
94 struct tegra_output *rgb;
95
96 struct list_head list;
97
98 struct drm_info_list *debugfs_files;
99 struct drm_minor *minor;
100 struct dentry *debugfs;
101
102 /* page-flip handling */
103 struct drm_pending_vblank_event *event;
104};
105
106static inline struct tegra_dc *
107host1x_client_to_dc(struct host1x_client *client)
108{
109 return container_of(client, struct tegra_dc, client);
110}
111
112static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
113{
114 return container_of(crtc, struct tegra_dc, base);
115}
116
117static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
118 unsigned long reg)
119{
120 writel(value, dc->regs + (reg << 2));
121}
122
123static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
124 unsigned long reg)
125{
126 return readl(dc->regs + (reg << 2));
127}
128
129struct tegra_dc_window {
130 struct {
131 unsigned int x;
132 unsigned int y;
133 unsigned int w;
134 unsigned int h;
135 } src;
136 struct {
137 unsigned int x;
138 unsigned int y;
139 unsigned int w;
140 unsigned int h;
141 } dst;
142 unsigned int bits_per_pixel;
143 unsigned int format;
144 unsigned int stride[2];
145 unsigned long base[3];
146};
147
148/* from dc.c */
149extern unsigned int tegra_dc_format(uint32_t format);
150extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
151 const struct tegra_dc_window *window);
152extern void tegra_dc_enable_vblank(struct tegra_dc *dc);
153extern void tegra_dc_disable_vblank(struct tegra_dc *dc);
154extern void tegra_dc_cancel_page_flip(struct drm_crtc *crtc,
155 struct drm_file *file);
156
157struct tegra_output_ops {
158 int (*enable)(struct tegra_output *output);
159 int (*disable)(struct tegra_output *output);
160 int (*setup_clock)(struct tegra_output *output, struct clk *clk,
161 unsigned long pclk);
162 int (*check_mode)(struct tegra_output *output,
163 struct drm_display_mode *mode,
164 enum drm_mode_status *status);
165};
166
167enum tegra_output_type {
168 TEGRA_OUTPUT_RGB,
169 TEGRA_OUTPUT_HDMI,
170};
171
172struct tegra_output {
173 struct device_node *of_node;
174 struct device *dev;
175
176 const struct tegra_output_ops *ops;
177 enum tegra_output_type type;
178
179 struct i2c_adapter *ddc;
180 const struct edid *edid;
181 unsigned int hpd_irq;
182 int hpd_gpio;
183
184 struct drm_encoder encoder;
185 struct drm_connector connector;
186};
187
188static inline struct tegra_output *encoder_to_output(struct drm_encoder *e)
189{
190 return container_of(e, struct tegra_output, encoder);
191}
192
193static inline struct tegra_output *connector_to_output(struct drm_connector *c)
194{
195 return container_of(c, struct tegra_output, connector);
196}
197
198static inline int tegra_output_enable(struct tegra_output *output)
199{
200 if (output && output->ops && output->ops->enable)
201 return output->ops->enable(output);
202
203 return output ? -ENOSYS : -EINVAL;
204}
205
206static inline int tegra_output_disable(struct tegra_output *output)
207{
208 if (output && output->ops && output->ops->disable)
209 return output->ops->disable(output);
210
211 return output ? -ENOSYS : -EINVAL;
212}
213
214static inline int tegra_output_setup_clock(struct tegra_output *output,
215 struct clk *clk, unsigned long pclk)
216{
217 if (output && output->ops && output->ops->setup_clock)
218 return output->ops->setup_clock(output, clk, pclk);
219
220 return output ? -ENOSYS : -EINVAL;
221}
222
223static inline int tegra_output_check_mode(struct tegra_output *output,
224 struct drm_display_mode *mode,
225 enum drm_mode_status *status)
226{
227 if (output && output->ops && output->ops->check_mode)
228 return output->ops->check_mode(output, mode, status);
229
230 return output ? -ENOSYS : -EINVAL;
231}
232
233/* from bus.c */
234int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device);
235void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device);
236
237/* from rgb.c */
238extern int tegra_dc_rgb_probe(struct tegra_dc *dc);
239extern int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc);
240extern int tegra_dc_rgb_exit(struct tegra_dc *dc);
241
242/* from output.c */
243extern int tegra_output_parse_dt(struct tegra_output *output);
244extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
245extern int tegra_output_exit(struct tegra_output *output);
246
247/* from fb.c */
248struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
249 unsigned int index);
250extern int tegra_drm_fb_init(struct drm_device *drm);
251extern void tegra_drm_fb_exit(struct drm_device *drm);
252extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
253
254extern struct platform_driver tegra_dc_driver;
255extern struct platform_driver tegra_hdmi_driver;
256extern struct platform_driver tegra_gr2d_driver;
257
258#endif /* HOST1X_DRM_H */
diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c
deleted file mode 100644
index 1fd4e196b934..000000000000
--- a/drivers/gpu/host1x/drm/fb.c
+++ /dev/null
@@ -1,372 +0,0 @@
1/*
2 * Copyright (C) 2012-2013 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * Based on the KMS/FB CMA helpers
6 * Copyright (C) 2012 Analog Device Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include "drm.h"
14#include "gem.h"
15
16static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
17{
18 return container_of(fb, struct tegra_fb, base);
19}
20
21static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
22{
23 return container_of(helper, struct tegra_fbdev, base);
24}
25
26struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
27 unsigned int index)
28{
29 struct tegra_fb *fb = to_tegra_fb(framebuffer);
30
31 if (index >= drm_format_num_planes(framebuffer->pixel_format))
32 return NULL;
33
34 return fb->planes[index];
35}
36
37static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
38{
39 struct tegra_fb *fb = to_tegra_fb(framebuffer);
40 unsigned int i;
41
42 for (i = 0; i < fb->num_planes; i++) {
43 struct tegra_bo *bo = fb->planes[i];
44
45 if (bo)
46 drm_gem_object_unreference_unlocked(&bo->gem);
47 }
48
49 drm_framebuffer_cleanup(framebuffer);
50 kfree(fb->planes);
51 kfree(fb);
52}
53
54static int tegra_fb_create_handle(struct drm_framebuffer *framebuffer,
55 struct drm_file *file, unsigned int *handle)
56{
57 struct tegra_fb *fb = to_tegra_fb(framebuffer);
58
59 return drm_gem_handle_create(file, &fb->planes[0]->gem, handle);
60}
61
62static struct drm_framebuffer_funcs tegra_fb_funcs = {
63 .destroy = tegra_fb_destroy,
64 .create_handle = tegra_fb_create_handle,
65};
66
67static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm,
68 struct drm_mode_fb_cmd2 *mode_cmd,
69 struct tegra_bo **planes,
70 unsigned int num_planes)
71{
72 struct tegra_fb *fb;
73 unsigned int i;
74 int err;
75
76 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
77 if (!fb)
78 return ERR_PTR(-ENOMEM);
79
80 fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL);
81 if (!fb->planes)
82 return ERR_PTR(-ENOMEM);
83
84 fb->num_planes = num_planes;
85
86 drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
87
88 for (i = 0; i < fb->num_planes; i++)
89 fb->planes[i] = planes[i];
90
91 err = drm_framebuffer_init(drm, &fb->base, &tegra_fb_funcs);
92 if (err < 0) {
93 dev_err(drm->dev, "failed to initialize framebuffer: %d\n",
94 err);
95 kfree(fb->planes);
96 kfree(fb);
97 return ERR_PTR(err);
98 }
99
100 return fb;
101}
102
103static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
104 struct drm_file *file,
105 struct drm_mode_fb_cmd2 *cmd)
106{
107 unsigned int hsub, vsub, i;
108 struct tegra_bo *planes[4];
109 struct drm_gem_object *gem;
110 struct tegra_fb *fb;
111 int err;
112
113 hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format);
114 vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format);
115
116 for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) {
117 unsigned int width = cmd->width / (i ? hsub : 1);
118 unsigned int height = cmd->height / (i ? vsub : 1);
119 unsigned int size, bpp;
120
121 gem = drm_gem_object_lookup(drm, file, cmd->handles[i]);
122 if (!gem) {
123 err = -ENXIO;
124 goto unreference;
125 }
126
127 bpp = drm_format_plane_cpp(cmd->pixel_format, i);
128
129 size = (height - 1) * cmd->pitches[i] +
130 width * bpp + cmd->offsets[i];
131
132 if (gem->size < size) {
133 err = -EINVAL;
134 goto unreference;
135 }
136
137 planes[i] = to_tegra_bo(gem);
138 }
139
140 fb = tegra_fb_alloc(drm, cmd, planes, i);
141 if (IS_ERR(fb)) {
142 err = PTR_ERR(fb);
143 goto unreference;
144 }
145
146 return &fb->base;
147
148unreference:
149 while (i--)
150 drm_gem_object_unreference_unlocked(&planes[i]->gem);
151
152 return ERR_PTR(err);
153}
154
155static struct fb_ops tegra_fb_ops = {
156 .owner = THIS_MODULE,
157 .fb_fillrect = sys_fillrect,
158 .fb_copyarea = sys_copyarea,
159 .fb_imageblit = sys_imageblit,
160 .fb_check_var = drm_fb_helper_check_var,
161 .fb_set_par = drm_fb_helper_set_par,
162 .fb_blank = drm_fb_helper_blank,
163 .fb_pan_display = drm_fb_helper_pan_display,
164 .fb_setcmap = drm_fb_helper_setcmap,
165};
166
167static int tegra_fbdev_probe(struct drm_fb_helper *helper,
168 struct drm_fb_helper_surface_size *sizes)
169{
170 struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
171 struct drm_device *drm = helper->dev;
172 struct drm_mode_fb_cmd2 cmd = { 0 };
173 unsigned int bytes_per_pixel;
174 struct drm_framebuffer *fb;
175 unsigned long offset;
176 struct fb_info *info;
177 struct tegra_bo *bo;
178 size_t size;
179 int err;
180
181 bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
182
183 cmd.width = sizes->surface_width;
184 cmd.height = sizes->surface_height;
185 cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
186 cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
187 sizes->surface_depth);
188
189 size = cmd.pitches[0] * cmd.height;
190
191 bo = tegra_bo_create(drm, size);
192 if (IS_ERR(bo))
193 return PTR_ERR(bo);
194
195 info = framebuffer_alloc(0, drm->dev);
196 if (!info) {
197 dev_err(drm->dev, "failed to allocate framebuffer info\n");
198 tegra_bo_free_object(&bo->gem);
199 return -ENOMEM;
200 }
201
202 fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1);
203 if (IS_ERR(fbdev->fb)) {
204 dev_err(drm->dev, "failed to allocate DRM framebuffer\n");
205 err = PTR_ERR(fbdev->fb);
206 goto release;
207 }
208
209 fb = &fbdev->fb->base;
210 helper->fb = fb;
211 helper->fbdev = info;
212
213 info->par = helper;
214 info->flags = FBINFO_FLAG_DEFAULT;
215 info->fbops = &tegra_fb_ops;
216
217 err = fb_alloc_cmap(&info->cmap, 256, 0);
218 if (err < 0) {
219 dev_err(drm->dev, "failed to allocate color map: %d\n", err);
220 goto destroy;
221 }
222
223 drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
224 drm_fb_helper_fill_var(info, helper, fb->width, fb->height);
225
226 offset = info->var.xoffset * bytes_per_pixel +
227 info->var.yoffset * fb->pitches[0];
228
229 drm->mode_config.fb_base = (resource_size_t)bo->paddr;
230 info->screen_base = bo->vaddr + offset;
231 info->screen_size = size;
232 info->fix.smem_start = (unsigned long)(bo->paddr + offset);
233 info->fix.smem_len = size;
234
235 return 0;
236
237destroy:
238 drm_framebuffer_unregister_private(fb);
239 tegra_fb_destroy(fb);
240release:
241 framebuffer_release(info);
242 return err;
243}
244
245static struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
246 .fb_probe = tegra_fbdev_probe,
247};
248
249static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
250 unsigned int preferred_bpp,
251 unsigned int num_crtc,
252 unsigned int max_connectors)
253{
254 struct drm_fb_helper *helper;
255 struct tegra_fbdev *fbdev;
256 int err;
257
258 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
259 if (!fbdev) {
260 dev_err(drm->dev, "failed to allocate DRM fbdev\n");
261 return ERR_PTR(-ENOMEM);
262 }
263
264 fbdev->base.funcs = &tegra_fb_helper_funcs;
265 helper = &fbdev->base;
266
267 err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
268 if (err < 0) {
269 dev_err(drm->dev, "failed to initialize DRM FB helper\n");
270 goto free;
271 }
272
273 err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
274 if (err < 0) {
275 dev_err(drm->dev, "failed to add connectors\n");
276 goto fini;
277 }
278
279 drm_helper_disable_unused_functions(drm);
280
281 err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
282 if (err < 0) {
283 dev_err(drm->dev, "failed to set initial configuration\n");
284 goto fini;
285 }
286
287 return fbdev;
288
289fini:
290 drm_fb_helper_fini(&fbdev->base);
291free:
292 kfree(fbdev);
293 return ERR_PTR(err);
294}
295
296static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
297{
298 struct fb_info *info = fbdev->base.fbdev;
299
300 if (info) {
301 int err;
302
303 err = unregister_framebuffer(info);
304 if (err < 0)
305 DRM_DEBUG_KMS("failed to unregister framebuffer\n");
306
307 if (info->cmap.len)
308 fb_dealloc_cmap(&info->cmap);
309
310 framebuffer_release(info);
311 }
312
313 if (fbdev->fb) {
314 drm_framebuffer_unregister_private(&fbdev->fb->base);
315 tegra_fb_destroy(&fbdev->fb->base);
316 }
317
318 drm_fb_helper_fini(&fbdev->base);
319 kfree(fbdev);
320}
321
322static void tegra_fb_output_poll_changed(struct drm_device *drm)
323{
324 struct tegra_drm *tegra = drm->dev_private;
325
326 if (tegra->fbdev)
327 drm_fb_helper_hotplug_event(&tegra->fbdev->base);
328}
329
330static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
331 .fb_create = tegra_fb_create,
332 .output_poll_changed = tegra_fb_output_poll_changed,
333};
334
335int tegra_drm_fb_init(struct drm_device *drm)
336{
337 struct tegra_drm *tegra = drm->dev_private;
338 struct tegra_fbdev *fbdev;
339
340 drm->mode_config.min_width = 0;
341 drm->mode_config.min_height = 0;
342
343 drm->mode_config.max_width = 4096;
344 drm->mode_config.max_height = 4096;
345
346 drm->mode_config.funcs = &tegra_drm_mode_funcs;
347
348 fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
349 drm->mode_config.num_connector);
350 if (IS_ERR(fbdev))
351 return PTR_ERR(fbdev);
352
353 tegra->fbdev = fbdev;
354
355 return 0;
356}
357
358void tegra_drm_fb_exit(struct drm_device *drm)
359{
360 struct tegra_drm *tegra = drm->dev_private;
361
362 tegra_fbdev_free(tegra->fbdev);
363}
364
365void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
366{
367 if (fbdev) {
368 drm_modeset_lock_all(fbdev->base.dev);
369 drm_fb_helper_restore_fbdev_mode(&fbdev->base);
370 drm_modeset_unlock_all(fbdev->base.dev);
371 }
372}
diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c
deleted file mode 100644
index 267c0c21e5cc..000000000000
--- a/drivers/gpu/host1x/drm/gem.c
+++ /dev/null
@@ -1,248 +0,0 @@
1/*
2 * NVIDIA Tegra DRM GEM helper functions
3 *
4 * Copyright (C) 2012 Sascha Hauer, Pengutronix
5 * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved.
6 *
7 * Based on the GEM/CMA helpers
8 *
9 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21#include "gem.h"
22
23static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
24{
25 return container_of(bo, struct tegra_bo, base);
26}
27
28static void tegra_bo_put(struct host1x_bo *bo)
29{
30 struct tegra_bo *obj = host1x_to_tegra_bo(bo);
31 struct drm_device *drm = obj->gem.dev;
32
33 mutex_lock(&drm->struct_mutex);
34 drm_gem_object_unreference(&obj->gem);
35 mutex_unlock(&drm->struct_mutex);
36}
37
38static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
39{
40 struct tegra_bo *obj = host1x_to_tegra_bo(bo);
41
42 return obj->paddr;
43}
44
45static void tegra_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt)
46{
47}
48
49static void *tegra_bo_mmap(struct host1x_bo *bo)
50{
51 struct tegra_bo *obj = host1x_to_tegra_bo(bo);
52
53 return obj->vaddr;
54}
55
56static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
57{
58}
59
60static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page)
61{
62 struct tegra_bo *obj = host1x_to_tegra_bo(bo);
63
64 return obj->vaddr + page * PAGE_SIZE;
65}
66
67static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page,
68 void *addr)
69{
70}
71
72static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
73{
74 struct tegra_bo *obj = host1x_to_tegra_bo(bo);
75 struct drm_device *drm = obj->gem.dev;
76
77 mutex_lock(&drm->struct_mutex);
78 drm_gem_object_reference(&obj->gem);
79 mutex_unlock(&drm->struct_mutex);
80
81 return bo;
82}
83
84const struct host1x_bo_ops tegra_bo_ops = {
85 .get = tegra_bo_get,
86 .put = tegra_bo_put,
87 .pin = tegra_bo_pin,
88 .unpin = tegra_bo_unpin,
89 .mmap = tegra_bo_mmap,
90 .munmap = tegra_bo_munmap,
91 .kmap = tegra_bo_kmap,
92 .kunmap = tegra_bo_kunmap,
93};
94
95static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo)
96{
97 dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr);
98}
99
100struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size)
101{
102 struct tegra_bo *bo;
103 int err;
104
105 bo = kzalloc(sizeof(*bo), GFP_KERNEL);
106 if (!bo)
107 return ERR_PTR(-ENOMEM);
108
109 host1x_bo_init(&bo->base, &tegra_bo_ops);
110 size = round_up(size, PAGE_SIZE);
111
112 bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr,
113 GFP_KERNEL | __GFP_NOWARN);
114 if (!bo->vaddr) {
115 dev_err(drm->dev, "failed to allocate buffer with size %u\n",
116 size);
117 err = -ENOMEM;
118 goto err_dma;
119 }
120
121 err = drm_gem_object_init(drm, &bo->gem, size);
122 if (err)
123 goto err_init;
124
125 err = drm_gem_create_mmap_offset(&bo->gem);
126 if (err)
127 goto err_mmap;
128
129 return bo;
130
131err_mmap:
132 drm_gem_object_release(&bo->gem);
133err_init:
134 tegra_bo_destroy(drm, bo);
135err_dma:
136 kfree(bo);
137
138 return ERR_PTR(err);
139
140}
141
142struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
143 struct drm_device *drm,
144 unsigned int size,
145 unsigned int *handle)
146{
147 struct tegra_bo *bo;
148 int ret;
149
150 bo = tegra_bo_create(drm, size);
151 if (IS_ERR(bo))
152 return bo;
153
154 ret = drm_gem_handle_create(file, &bo->gem, handle);
155 if (ret)
156 goto err;
157
158 drm_gem_object_unreference_unlocked(&bo->gem);
159
160 return bo;
161
162err:
163 tegra_bo_free_object(&bo->gem);
164 return ERR_PTR(ret);
165}
166
167void tegra_bo_free_object(struct drm_gem_object *gem)
168{
169 struct tegra_bo *bo = to_tegra_bo(gem);
170
171 drm_gem_free_mmap_offset(gem);
172 drm_gem_object_release(gem);
173 tegra_bo_destroy(gem->dev, bo);
174
175 kfree(bo);
176}
177
178int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
179 struct drm_mode_create_dumb *args)
180{
181 int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
182 struct tegra_bo *bo;
183
184 if (args->pitch < min_pitch)
185 args->pitch = min_pitch;
186
187 if (args->size < args->pitch * args->height)
188 args->size = args->pitch * args->height;
189
190 bo = tegra_bo_create_with_handle(file, drm, args->size,
191 &args->handle);
192 if (IS_ERR(bo))
193 return PTR_ERR(bo);
194
195 return 0;
196}
197
198int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
199 uint32_t handle, uint64_t *offset)
200{
201 struct drm_gem_object *gem;
202 struct tegra_bo *bo;
203
204 mutex_lock(&drm->struct_mutex);
205
206 gem = drm_gem_object_lookup(drm, file, handle);
207 if (!gem) {
208 dev_err(drm->dev, "failed to lookup GEM object\n");
209 mutex_unlock(&drm->struct_mutex);
210 return -EINVAL;
211 }
212
213 bo = to_tegra_bo(gem);
214
215 *offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
216
217 drm_gem_object_unreference(gem);
218
219 mutex_unlock(&drm->struct_mutex);
220
221 return 0;
222}
223
224const struct vm_operations_struct tegra_bo_vm_ops = {
225 .open = drm_gem_vm_open,
226 .close = drm_gem_vm_close,
227};
228
229int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
230{
231 struct drm_gem_object *gem;
232 struct tegra_bo *bo;
233 int ret;
234
235 ret = drm_gem_mmap(file, vma);
236 if (ret)
237 return ret;
238
239 gem = vma->vm_private_data;
240 bo = to_tegra_bo(gem);
241
242 ret = remap_pfn_range(vma, vma->vm_start, bo->paddr >> PAGE_SHIFT,
243 vma->vm_end - vma->vm_start, vma->vm_page_prot);
244 if (ret)
245 drm_gem_vm_close(vma);
246
247 return ret;
248}
diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/host1x/drm/gem.h
deleted file mode 100644
index 2b54f1425d5e..000000000000
--- a/drivers/gpu/host1x/drm/gem.h
+++ /dev/null
@@ -1,56 +0,0 @@
1/*
2 * Tegra host1x GEM implementation
3 *
4 * Copyright (c) 2012-2013, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef __HOST1X_GEM_H
20#define __HOST1X_GEM_H
21
22#include <linux/host1x.h>
23
24#include <drm/drm.h>
25#include <drm/drmP.h>
26
27struct tegra_bo {
28 struct drm_gem_object gem;
29 struct host1x_bo base;
30 dma_addr_t paddr;
31 void *vaddr;
32};
33
34static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
35{
36 return container_of(gem, struct tegra_bo, gem);
37}
38
39extern const struct host1x_bo_ops tegra_bo_ops;
40
41struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size);
42struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
43 struct drm_device *drm,
44 unsigned int size,
45 unsigned int *handle);
46void tegra_bo_free_object(struct drm_gem_object *gem);
47int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
48 struct drm_mode_create_dumb *args);
49int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
50 uint32_t handle, uint64_t *offset);
51
52int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma);
53
54extern const struct vm_operations_struct tegra_bo_vm_ops;
55
56#endif
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
deleted file mode 100644
index 4e407e30da1c..000000000000
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ /dev/null
@@ -1,343 +0,0 @@
1/*
2 * Copyright (c) 2012-2013, NVIDIA Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/clk.h>
18
19#include "drm.h"
20#include "gem.h"
21
22#define GR2D_NUM_REGS 0x4d
23
24struct gr2d {
25 struct tegra_drm_client client;
26 struct host1x_channel *channel;
27 struct clk *clk;
28
29 DECLARE_BITMAP(addr_regs, GR2D_NUM_REGS);
30};
31
32static inline struct gr2d *to_gr2d(struct tegra_drm_client *client)
33{
34 return container_of(client, struct gr2d, client);
35}
36
37static int gr2d_init(struct host1x_client *client)
38{
39 struct tegra_drm_client *drm = host1x_to_drm_client(client);
40 struct tegra_drm *tegra = dev_get_drvdata(client->parent);
41 struct gr2d *gr2d = to_gr2d(drm);
42
43 gr2d->channel = host1x_channel_request(client->dev);
44 if (!gr2d->channel)
45 return -ENOMEM;
46
47 client->syncpts[0] = host1x_syncpt_request(client->dev, false);
48 if (!client->syncpts[0]) {
49 host1x_channel_free(gr2d->channel);
50 return -ENOMEM;
51 }
52
53 return tegra_drm_register_client(tegra, drm);
54}
55
56static int gr2d_exit(struct host1x_client *client)
57{
58 struct tegra_drm_client *drm = host1x_to_drm_client(client);
59 struct tegra_drm *tegra = dev_get_drvdata(client->parent);
60 struct gr2d *gr2d = to_gr2d(drm);
61 int err;
62
63 err = tegra_drm_unregister_client(tegra, drm);
64 if (err < 0)
65 return err;
66
67 host1x_syncpt_free(client->syncpts[0]);
68 host1x_channel_free(gr2d->channel);
69
70 return 0;
71}
72
73static const struct host1x_client_ops gr2d_client_ops = {
74 .init = gr2d_init,
75 .exit = gr2d_exit,
76};
77
78static int gr2d_open_channel(struct tegra_drm_client *client,
79 struct tegra_drm_context *context)
80{
81 struct gr2d *gr2d = to_gr2d(client);
82
83 context->channel = host1x_channel_get(gr2d->channel);
84 if (!context->channel)
85 return -ENOMEM;
86
87 return 0;
88}
89
90static void gr2d_close_channel(struct tegra_drm_context *context)
91{
92 host1x_channel_put(context->channel);
93}
94
95static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm,
96 struct drm_file *file,
97 u32 handle)
98{
99 struct drm_gem_object *gem;
100 struct tegra_bo *bo;
101
102 gem = drm_gem_object_lookup(drm, file, handle);
103 if (!gem)
104 return NULL;
105
106 mutex_lock(&drm->struct_mutex);
107 drm_gem_object_unreference(gem);
108 mutex_unlock(&drm->struct_mutex);
109
110 bo = to_tegra_bo(gem);
111 return &bo->base;
112}
113
114static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
115{
116 struct gr2d *gr2d = dev_get_drvdata(dev);
117
118 switch (class) {
119 case HOST1X_CLASS_HOST1X:
120 if (offset == 0x2b)
121 return 1;
122
123 break;
124
125 case HOST1X_CLASS_GR2D:
126 case HOST1X_CLASS_GR2D_SB:
127 if (offset >= GR2D_NUM_REGS)
128 break;
129
130 if (test_bit(offset, gr2d->addr_regs))
131 return 1;
132
133 break;
134 }
135
136 return 0;
137}
138
139static int gr2d_submit(struct tegra_drm_context *context,
140 struct drm_tegra_submit *args, struct drm_device *drm,
141 struct drm_file *file)
142{
143 unsigned int num_cmdbufs = args->num_cmdbufs;
144 unsigned int num_relocs = args->num_relocs;
145 unsigned int num_waitchks = args->num_waitchks;
146 struct drm_tegra_cmdbuf __user *cmdbufs =
147 (void * __user)(uintptr_t)args->cmdbufs;
148 struct drm_tegra_reloc __user *relocs =
149 (void * __user)(uintptr_t)args->relocs;
150 struct drm_tegra_waitchk __user *waitchks =
151 (void * __user)(uintptr_t)args->waitchks;
152 struct drm_tegra_syncpt syncpt;
153 struct host1x_job *job;
154 int err;
155
156 /* We don't yet support other than one syncpt_incr struct per submit */
157 if (args->num_syncpts != 1)
158 return -EINVAL;
159
160 job = host1x_job_alloc(context->channel, args->num_cmdbufs,
161 args->num_relocs, args->num_waitchks);
162 if (!job)
163 return -ENOMEM;
164
165 job->num_relocs = args->num_relocs;
166 job->num_waitchk = args->num_waitchks;
167 job->client = (u32)args->context;
168 job->class = context->client->base.class;
169 job->serialize = true;
170
171 while (num_cmdbufs) {
172 struct drm_tegra_cmdbuf cmdbuf;
173 struct host1x_bo *bo;
174
175 err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf));
176 if (err)
177 goto fail;
178
179 bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
180 if (!bo) {
181 err = -ENOENT;
182 goto fail;
183 }
184
185 host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset);
186 num_cmdbufs--;
187 cmdbufs++;
188 }
189
190 err = copy_from_user(job->relocarray, relocs,
191 sizeof(*relocs) * num_relocs);
192 if (err)
193 goto fail;
194
195 while (num_relocs--) {
196 struct host1x_reloc *reloc = &job->relocarray[num_relocs];
197 struct host1x_bo *cmdbuf, *target;
198
199 cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf);
200 target = host1x_bo_lookup(drm, file, (u32)reloc->target);
201
202 reloc->cmdbuf = cmdbuf;
203 reloc->target = target;
204
205 if (!reloc->target || !reloc->cmdbuf) {
206 err = -ENOENT;
207 goto fail;
208 }
209 }
210
211 err = copy_from_user(job->waitchk, waitchks,
212 sizeof(*waitchks) * num_waitchks);
213 if (err)
214 goto fail;
215
216 err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts,
217 sizeof(syncpt));
218 if (err)
219 goto fail;
220
221 job->syncpt_id = syncpt.id;
222 job->syncpt_incrs = syncpt.incrs;
223 job->timeout = 10000;
224 job->is_addr_reg = gr2d_is_addr_reg;
225
226 if (args->timeout && args->timeout < 10000)
227 job->timeout = args->timeout;
228
229 err = host1x_job_pin(job, context->client->base.dev);
230 if (err)
231 goto fail;
232
233 err = host1x_job_submit(job);
234 if (err)
235 goto fail_submit;
236
237 args->fence = job->syncpt_end;
238
239 host1x_job_put(job);
240 return 0;
241
242fail_submit:
243 host1x_job_unpin(job);
244fail:
245 host1x_job_put(job);
246 return err;
247}
248
249static const struct tegra_drm_client_ops gr2d_ops = {
250 .open_channel = gr2d_open_channel,
251 .close_channel = gr2d_close_channel,
252 .submit = gr2d_submit,
253};
254
255static const struct of_device_id gr2d_match[] = {
256 { .compatible = "nvidia,tegra30-gr2d" },
257 { .compatible = "nvidia,tegra20-gr2d" },
258 { },
259};
260
261static const u32 gr2d_addr_regs[] = {
262 0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31, 0x32,
263 0x48, 0x49, 0x4a, 0x4b, 0x4c
264};
265
266static int gr2d_probe(struct platform_device *pdev)
267{
268 struct device *dev = &pdev->dev;
269 struct host1x_syncpt **syncpts;
270 struct gr2d *gr2d;
271 unsigned int i;
272 int err;
273
274 gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL);
275 if (!gr2d)
276 return -ENOMEM;
277
278 syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
279 if (!syncpts)
280 return -ENOMEM;
281
282 gr2d->clk = devm_clk_get(dev, NULL);
283 if (IS_ERR(gr2d->clk)) {
284 dev_err(dev, "cannot get clock\n");
285 return PTR_ERR(gr2d->clk);
286 }
287
288 err = clk_prepare_enable(gr2d->clk);
289 if (err) {
290 dev_err(dev, "cannot turn on clock\n");
291 return err;
292 }
293
294 INIT_LIST_HEAD(&gr2d->client.base.list);
295 gr2d->client.base.ops = &gr2d_client_ops;
296 gr2d->client.base.dev = dev;
297 gr2d->client.base.class = HOST1X_CLASS_GR2D;
298 gr2d->client.base.syncpts = syncpts;
299 gr2d->client.base.num_syncpts = 1;
300
301 INIT_LIST_HEAD(&gr2d->client.list);
302 gr2d->client.ops = &gr2d_ops;
303
304 err = host1x_client_register(&gr2d->client.base);
305 if (err < 0) {
306 dev_err(dev, "failed to register host1x client: %d\n", err);
307 return err;
308 }
309
310 /* initialize address register map */
311 for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
312 set_bit(gr2d_addr_regs[i], gr2d->addr_regs);
313
314 platform_set_drvdata(pdev, gr2d);
315
316 return 0;
317}
318
319static int gr2d_remove(struct platform_device *pdev)
320{
321 struct gr2d *gr2d = platform_get_drvdata(pdev);
322 int err;
323
324 err = host1x_client_unregister(&gr2d->client.base);
325 if (err < 0) {
326 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
327 err);
328 return err;
329 }
330
331 clk_disable_unprepare(gr2d->clk);
332
333 return 0;
334}
335
336struct platform_driver tegra_gr2d_driver = {
337 .driver = {
338 .name = "tegra-gr2d",
339 .of_match_table = gr2d_match,
340 },
341 .probe = gr2d_probe,
342 .remove = gr2d_remove,
343};
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
deleted file mode 100644
index f5663d15670b..000000000000
--- a/drivers/gpu/host1x/drm/hdmi.c
+++ /dev/null
@@ -1,1295 +0,0 @@
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/clk/tegra.h>
12#include <linux/debugfs.h>
13#include <linux/hdmi.h>
14#include <linux/regulator/consumer.h>
15
16#include "hdmi.h"
17#include "drm.h"
18#include "dc.h"
19
20struct tegra_hdmi {
21 struct host1x_client client;
22 struct tegra_output output;
23 struct device *dev;
24
25 struct regulator *vdd;
26 struct regulator *pll;
27
28 void __iomem *regs;
29 unsigned int irq;
30
31 struct clk *clk_parent;
32 struct clk *clk;
33
34 unsigned int audio_source;
35 unsigned int audio_freq;
36 bool stereo;
37 bool dvi;
38
39 struct drm_info_list *debugfs_files;
40 struct drm_minor *minor;
41 struct dentry *debugfs;
42};
43
44static inline struct tegra_hdmi *
45host1x_client_to_hdmi(struct host1x_client *client)
46{
47 return container_of(client, struct tegra_hdmi, client);
48}
49
50static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
51{
52 return container_of(output, struct tegra_hdmi, output);
53}
54
55#define HDMI_AUDIOCLK_FREQ 216000000
56#define HDMI_REKEY_DEFAULT 56
57
58enum {
59 AUTO = 0,
60 SPDIF,
61 HDA,
62};
63
64static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi,
65 unsigned long reg)
66{
67 return readl(hdmi->regs + (reg << 2));
68}
69
70static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val,
71 unsigned long reg)
72{
73 writel(val, hdmi->regs + (reg << 2));
74}
75
76struct tegra_hdmi_audio_config {
77 unsigned int pclk;
78 unsigned int n;
79 unsigned int cts;
80 unsigned int aval;
81};
82
83static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
84 { 25200000, 4096, 25200, 24000 },
85 { 27000000, 4096, 27000, 24000 },
86 { 74250000, 4096, 74250, 24000 },
87 { 148500000, 4096, 148500, 24000 },
88 { 0, 0, 0, 0 },
89};
90
91static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
92 { 25200000, 5880, 26250, 25000 },
93 { 27000000, 5880, 28125, 25000 },
94 { 74250000, 4704, 61875, 20000 },
95 { 148500000, 4704, 123750, 20000 },
96 { 0, 0, 0, 0 },
97};
98
99static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
100 { 25200000, 6144, 25200, 24000 },
101 { 27000000, 6144, 27000, 24000 },
102 { 74250000, 6144, 74250, 24000 },
103 { 148500000, 6144, 148500, 24000 },
104 { 0, 0, 0, 0 },
105};
106
107static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
108 { 25200000, 11760, 26250, 25000 },
109 { 27000000, 11760, 28125, 25000 },
110 { 74250000, 9408, 61875, 20000 },
111 { 148500000, 9408, 123750, 20000 },
112 { 0, 0, 0, 0 },
113};
114
115static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
116 { 25200000, 12288, 25200, 24000 },
117 { 27000000, 12288, 27000, 24000 },
118 { 74250000, 12288, 74250, 24000 },
119 { 148500000, 12288, 148500, 24000 },
120 { 0, 0, 0, 0 },
121};
122
123static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
124 { 25200000, 23520, 26250, 25000 },
125 { 27000000, 23520, 28125, 25000 },
126 { 74250000, 18816, 61875, 20000 },
127 { 148500000, 18816, 123750, 20000 },
128 { 0, 0, 0, 0 },
129};
130
131static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
132 { 25200000, 24576, 25200, 24000 },
133 { 27000000, 24576, 27000, 24000 },
134 { 74250000, 24576, 74250, 24000 },
135 { 148500000, 24576, 148500, 24000 },
136 { 0, 0, 0, 0 },
137};
138
139struct tmds_config {
140 unsigned int pclk;
141 u32 pll0;
142 u32 pll1;
143 u32 pe_current;
144 u32 drive_current;
145};
146
147static const struct tmds_config tegra2_tmds_config[] = {
148 { /* slow pixel clock modes */
149 .pclk = 27000000,
150 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
151 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
152 SOR_PLL_TX_REG_LOAD(3),
153 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
154 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
155 PE_CURRENT1(PE_CURRENT_0_0_mA) |
156 PE_CURRENT2(PE_CURRENT_0_0_mA) |
157 PE_CURRENT3(PE_CURRENT_0_0_mA),
158 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
159 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
160 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
161 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
162 },
163 { /* high pixel clock modes */
164 .pclk = UINT_MAX,
165 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
166 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
167 SOR_PLL_TX_REG_LOAD(3),
168 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
169 .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
170 PE_CURRENT1(PE_CURRENT_6_0_mA) |
171 PE_CURRENT2(PE_CURRENT_6_0_mA) |
172 PE_CURRENT3(PE_CURRENT_6_0_mA),
173 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
174 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
175 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
176 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
177 },
178};
179
180static const struct tmds_config tegra3_tmds_config[] = {
181 { /* 480p modes */
182 .pclk = 27000000,
183 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
184 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
185 SOR_PLL_TX_REG_LOAD(0),
186 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
187 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
188 PE_CURRENT1(PE_CURRENT_0_0_mA) |
189 PE_CURRENT2(PE_CURRENT_0_0_mA) |
190 PE_CURRENT3(PE_CURRENT_0_0_mA),
191 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
192 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
193 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
194 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
195 }, { /* 720p modes */
196 .pclk = 74250000,
197 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
198 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
199 SOR_PLL_TX_REG_LOAD(0),
200 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
201 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
202 PE_CURRENT1(PE_CURRENT_5_0_mA) |
203 PE_CURRENT2(PE_CURRENT_5_0_mA) |
204 PE_CURRENT3(PE_CURRENT_5_0_mA),
205 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
206 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
207 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
208 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
209 }, { /* 1080p modes */
210 .pclk = UINT_MAX,
211 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
212 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
213 SOR_PLL_TX_REG_LOAD(0),
214 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
215 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
216 PE_CURRENT1(PE_CURRENT_5_0_mA) |
217 PE_CURRENT2(PE_CURRENT_5_0_mA) |
218 PE_CURRENT3(PE_CURRENT_5_0_mA),
219 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
220 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
221 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
222 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
223 },
224};
225
226static const struct tegra_hdmi_audio_config *
227tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
228{
229 const struct tegra_hdmi_audio_config *table;
230
231 switch (audio_freq) {
232 case 32000:
233 table = tegra_hdmi_audio_32k;
234 break;
235
236 case 44100:
237 table = tegra_hdmi_audio_44_1k;
238 break;
239
240 case 48000:
241 table = tegra_hdmi_audio_48k;
242 break;
243
244 case 88200:
245 table = tegra_hdmi_audio_88_2k;
246 break;
247
248 case 96000:
249 table = tegra_hdmi_audio_96k;
250 break;
251
252 case 176400:
253 table = tegra_hdmi_audio_176_4k;
254 break;
255
256 case 192000:
257 table = tegra_hdmi_audio_192k;
258 break;
259
260 default:
261 return NULL;
262 }
263
264 while (table->pclk) {
265 if (table->pclk == pclk)
266 return table;
267
268 table++;
269 }
270
271 return NULL;
272}
273
274static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
275{
276 const unsigned int freqs[] = {
277 32000, 44100, 48000, 88200, 96000, 176400, 192000
278 };
279 unsigned int i;
280
281 for (i = 0; i < ARRAY_SIZE(freqs); i++) {
282 unsigned int f = freqs[i];
283 unsigned int eight_half;
284 unsigned long value;
285 unsigned int delta;
286
287 if (f > 96000)
288 delta = 2;
289 else if (f > 480000)
290 delta = 6;
291 else
292 delta = 9;
293
294 eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
295 value = AUDIO_FS_LOW(eight_half - delta) |
296 AUDIO_FS_HIGH(eight_half + delta);
297 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i));
298 }
299}
300
301static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
302{
303 struct device_node *node = hdmi->dev->of_node;
304 const struct tegra_hdmi_audio_config *config;
305 unsigned int offset = 0;
306 unsigned long value;
307
308 switch (hdmi->audio_source) {
309 case HDA:
310 value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
311 break;
312
313 case SPDIF:
314 value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
315 break;
316
317 default:
318 value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
319 break;
320 }
321
322 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
323 value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
324 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
325 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
326 } else {
327 value |= AUDIO_CNTRL0_INJECT_NULLSMPL;
328 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
329
330 value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
331 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
332 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
333 }
334
335 config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
336 if (!config) {
337 dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
338 hdmi->audio_freq, pclk);
339 return -EINVAL;
340 }
341
342 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
343
344 value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
345 AUDIO_N_VALUE(config->n - 1);
346 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
347
348 tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
349 HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
350
351 value = ACR_SUBPACK_CTS(config->cts);
352 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
353
354 value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
355 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE);
356
357 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N);
358 value &= ~AUDIO_N_RESETF;
359 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
360
361 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
362 switch (hdmi->audio_freq) {
363 case 32000:
364 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320;
365 break;
366
367 case 44100:
368 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441;
369 break;
370
371 case 48000:
372 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480;
373 break;
374
375 case 88200:
376 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882;
377 break;
378
379 case 96000:
380 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960;
381 break;
382
383 case 176400:
384 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764;
385 break;
386
387 case 192000:
388 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920;
389 break;
390 }
391
392 tegra_hdmi_writel(hdmi, config->aval, offset);
393 }
394
395 tegra_hdmi_setup_audio_fs_tables(hdmi);
396
397 return 0;
398}
399
400static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size)
401{
402 unsigned long value = 0;
403 size_t i;
404
405 for (i = size; i > 0; i--)
406 value = (value << 8) | ptr[i - 1];
407
408 return value;
409}
410
411static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data,
412 size_t size)
413{
414 const u8 *ptr = data;
415 unsigned long offset;
416 unsigned long value;
417 size_t i, j;
418
419 switch (ptr[0]) {
420 case HDMI_INFOFRAME_TYPE_AVI:
421 offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER;
422 break;
423
424 case HDMI_INFOFRAME_TYPE_AUDIO:
425 offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER;
426 break;
427
428 case HDMI_INFOFRAME_TYPE_VENDOR:
429 offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER;
430 break;
431
432 default:
433 dev_err(hdmi->dev, "unsupported infoframe type: %02x\n",
434 ptr[0]);
435 return;
436 }
437
438 value = INFOFRAME_HEADER_TYPE(ptr[0]) |
439 INFOFRAME_HEADER_VERSION(ptr[1]) |
440 INFOFRAME_HEADER_LEN(ptr[2]);
441 tegra_hdmi_writel(hdmi, value, offset);
442 offset++;
443
444 /*
445 * Each subpack contains 7 bytes, divided into:
446 * - subpack_low: bytes 0 - 3
447 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
448 */
449 for (i = 3, j = 0; i < size; i += 7, j += 8) {
450 size_t rem = size - i, num = min_t(size_t, rem, 4);
451
452 value = tegra_hdmi_subpack(&ptr[i], num);
453 tegra_hdmi_writel(hdmi, value, offset++);
454
455 num = min_t(size_t, rem - num, 3);
456
457 value = tegra_hdmi_subpack(&ptr[i + 4], num);
458 tegra_hdmi_writel(hdmi, value, offset++);
459 }
460}
461
462static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
463 struct drm_display_mode *mode)
464{
465 struct hdmi_avi_infoframe frame;
466 u8 buffer[17];
467 ssize_t err;
468
469 if (hdmi->dvi) {
470 tegra_hdmi_writel(hdmi, 0,
471 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
472 return;
473 }
474
475 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
476 if (err < 0) {
477 dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
478 return;
479 }
480
481 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
482 if (err < 0) {
483 dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err);
484 return;
485 }
486
487 tegra_hdmi_write_infopack(hdmi, buffer, err);
488
489 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
490 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
491}
492
493static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
494{
495 struct hdmi_audio_infoframe frame;
496 u8 buffer[14];
497 ssize_t err;
498
499 if (hdmi->dvi) {
500 tegra_hdmi_writel(hdmi, 0,
501 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
502 return;
503 }
504
505 err = hdmi_audio_infoframe_init(&frame);
506 if (err < 0) {
507 dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n",
508 err);
509 return;
510 }
511
512 frame.channels = 2;
513
514 err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
515 if (err < 0) {
516 dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n",
517 err);
518 return;
519 }
520
521 /*
522 * The audio infoframe has only one set of subpack registers, so the
523 * infoframe needs to be truncated. One set of subpack registers can
524 * contain 7 bytes. Including the 3 byte header only the first 10
525 * bytes can be programmed.
526 */
527 tegra_hdmi_write_infopack(hdmi, buffer, min(10, err));
528
529 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
530 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
531}
532
533static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
534{
535 struct hdmi_vendor_infoframe frame;
536 unsigned long value;
537 u8 buffer[10];
538 ssize_t err;
539
540 if (!hdmi->stereo) {
541 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
542 value &= ~GENERIC_CTRL_ENABLE;
543 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
544 return;
545 }
546
547 hdmi_vendor_infoframe_init(&frame);
548 frame.s3d_struct = HDMI_3D_STRUCTURE_FRAME_PACKING;
549
550 err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
551 if (err < 0) {
552 dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n",
553 err);
554 return;
555 }
556
557 tegra_hdmi_write_infopack(hdmi, buffer, err);
558
559 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
560 value |= GENERIC_CTRL_ENABLE;
561 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
562}
563
564static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
565 const struct tmds_config *tmds)
566{
567 unsigned long value;
568
569 tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
570 tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
571 tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
572
573 value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
574 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
575}
576
577static int tegra_output_hdmi_enable(struct tegra_output *output)
578{
579 unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
580 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
581 struct drm_display_mode *mode = &dc->base.mode;
582 struct tegra_hdmi *hdmi = to_hdmi(output);
583 struct device_node *node = hdmi->dev->of_node;
584 unsigned int pulse_start, div82, pclk;
585 const struct tmds_config *tmds;
586 unsigned int num_tmds;
587 unsigned long value;
588 int retries = 1000;
589 int err;
590
591 pclk = mode->clock * 1000;
592 h_sync_width = mode->hsync_end - mode->hsync_start;
593 h_back_porch = mode->htotal - mode->hsync_end;
594 h_front_porch = mode->hsync_start - mode->hdisplay;
595
596 err = regulator_enable(hdmi->vdd);
597 if (err < 0) {
598 dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
599 return err;
600 }
601
602 err = regulator_enable(hdmi->pll);
603 if (err < 0) {
604 dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
605 return err;
606 }
607
608 /*
609 * This assumes that the display controller will divide its parent
610 * clock by 2 to generate the pixel clock.
611 */
612 err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2);
613 if (err < 0) {
614 dev_err(hdmi->dev, "failed to setup clock: %d\n", err);
615 return err;
616 }
617
618 err = clk_set_rate(hdmi->clk, pclk);
619 if (err < 0)
620 return err;
621
622 err = clk_enable(hdmi->clk);
623 if (err < 0) {
624 dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
625 return err;
626 }
627
628 tegra_periph_reset_assert(hdmi->clk);
629 usleep_range(1000, 2000);
630 tegra_periph_reset_deassert(hdmi->clk);
631
632 tegra_dc_writel(dc, VSYNC_H_POSITION(1),
633 DC_DISP_DISP_TIMING_OPTIONS);
634 tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
635 DC_DISP_DISP_COLOR_CONTROL);
636
637 /* video_preamble uses h_pulse2 */
638 pulse_start = 1 + h_sync_width + h_back_porch - 10;
639
640 tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
641
642 value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
643 PULSE_LAST_END_A;
644 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
645
646 value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
647 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
648
649 value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
650 VSYNC_WINDOW_ENABLE;
651 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
652
653 if (dc->pipe)
654 value = HDMI_SRC_DISPLAYB;
655 else
656 value = HDMI_SRC_DISPLAYA;
657
658 if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) ||
659 (mode->vdisplay == 576)))
660 tegra_hdmi_writel(hdmi,
661 value | ARM_VIDEO_RANGE_FULL,
662 HDMI_NV_PDISP_INPUT_CONTROL);
663 else
664 tegra_hdmi_writel(hdmi,
665 value | ARM_VIDEO_RANGE_LIMITED,
666 HDMI_NV_PDISP_INPUT_CONTROL);
667
668 div82 = clk_get_rate(hdmi->clk) / 1000000 * 4;
669 value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
670 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK);
671
672 if (!hdmi->dvi) {
673 err = tegra_hdmi_setup_audio(hdmi, pclk);
674 if (err < 0)
675 hdmi->dvi = true;
676 }
677
678 if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) {
679 /*
680 * TODO: add ELD support
681 */
682 }
683
684 rekey = HDMI_REKEY_DEFAULT;
685 value = HDMI_CTRL_REKEY(rekey);
686 value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch +
687 h_front_porch - rekey - 18) / 32);
688
689 if (!hdmi->dvi)
690 value |= HDMI_CTRL_ENABLE;
691
692 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL);
693
694 if (hdmi->dvi)
695 tegra_hdmi_writel(hdmi, 0x0,
696 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
697 else
698 tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
699 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
700
701 tegra_hdmi_setup_avi_infoframe(hdmi, mode);
702 tegra_hdmi_setup_audio_infoframe(hdmi);
703 tegra_hdmi_setup_stereo_infoframe(hdmi);
704
705 /* TMDS CONFIG */
706 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
707 num_tmds = ARRAY_SIZE(tegra3_tmds_config);
708 tmds = tegra3_tmds_config;
709 } else {
710 num_tmds = ARRAY_SIZE(tegra2_tmds_config);
711 tmds = tegra2_tmds_config;
712 }
713
714 for (i = 0; i < num_tmds; i++) {
715 if (pclk <= tmds[i].pclk) {
716 tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
717 break;
718 }
719 }
720
721 tegra_hdmi_writel(hdmi,
722 SOR_SEQ_CTL_PU_PC(0) |
723 SOR_SEQ_PU_PC_ALT(0) |
724 SOR_SEQ_PD_PC(8) |
725 SOR_SEQ_PD_PC_ALT(8),
726 HDMI_NV_PDISP_SOR_SEQ_CTL);
727
728 value = SOR_SEQ_INST_WAIT_TIME(1) |
729 SOR_SEQ_INST_WAIT_UNITS_VSYNC |
730 SOR_SEQ_INST_HALT |
731 SOR_SEQ_INST_PIN_A_LOW |
732 SOR_SEQ_INST_PIN_B_LOW |
733 SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
734
735 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0));
736 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8));
737
738 value = 0x1c800;
739 value &= ~SOR_CSTM_ROTCLK(~0);
740 value |= SOR_CSTM_ROTCLK(2);
741 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
742
743 tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
744 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
745 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
746
747 /* start SOR */
748 tegra_hdmi_writel(hdmi,
749 SOR_PWR_NORMAL_STATE_PU |
750 SOR_PWR_NORMAL_START_NORMAL |
751 SOR_PWR_SAFE_STATE_PD |
752 SOR_PWR_SETTING_NEW_TRIGGER,
753 HDMI_NV_PDISP_SOR_PWR);
754 tegra_hdmi_writel(hdmi,
755 SOR_PWR_NORMAL_STATE_PU |
756 SOR_PWR_NORMAL_START_NORMAL |
757 SOR_PWR_SAFE_STATE_PD |
758 SOR_PWR_SETTING_NEW_DONE,
759 HDMI_NV_PDISP_SOR_PWR);
760
761 do {
762 BUG_ON(--retries < 0);
763 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
764 } while (value & SOR_PWR_SETTING_NEW_PENDING);
765
766 value = SOR_STATE_ASY_CRCMODE_COMPLETE |
767 SOR_STATE_ASY_OWNER_HEAD0 |
768 SOR_STATE_ASY_SUBOWNER_BOTH |
769 SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
770 SOR_STATE_ASY_DEPOL_POS;
771
772 /* setup sync polarities */
773 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
774 value |= SOR_STATE_ASY_HSYNCPOL_POS;
775
776 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
777 value |= SOR_STATE_ASY_HSYNCPOL_NEG;
778
779 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
780 value |= SOR_STATE_ASY_VSYNCPOL_POS;
781
782 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
783 value |= SOR_STATE_ASY_VSYNCPOL_NEG;
784
785 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2);
786
787 value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
788 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1);
789
790 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
791 tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
792 tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED,
793 HDMI_NV_PDISP_SOR_STATE1);
794 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
795
796 tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
797
798 value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
799 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
800 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
801
802 value = DISP_CTRL_MODE_C_DISPLAY;
803 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
804
805 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
806 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
807
808 /* TODO: add HDCP support */
809
810 return 0;
811}
812
813static int tegra_output_hdmi_disable(struct tegra_output *output)
814{
815 struct tegra_hdmi *hdmi = to_hdmi(output);
816
817 tegra_periph_reset_assert(hdmi->clk);
818 clk_disable(hdmi->clk);
819 regulator_disable(hdmi->pll);
820 regulator_disable(hdmi->vdd);
821
822 return 0;
823}
824
825static int tegra_output_hdmi_setup_clock(struct tegra_output *output,
826 struct clk *clk, unsigned long pclk)
827{
828 struct tegra_hdmi *hdmi = to_hdmi(output);
829 struct clk *base;
830 int err;
831
832 err = clk_set_parent(clk, hdmi->clk_parent);
833 if (err < 0) {
834 dev_err(output->dev, "failed to set parent: %d\n", err);
835 return err;
836 }
837
838 base = clk_get_parent(hdmi->clk_parent);
839
840 /*
841 * This assumes that the parent clock is pll_d_out0 or pll_d2_out
842 * respectively, each of which divides the base pll_d by 2.
843 */
844 err = clk_set_rate(base, pclk * 2);
845 if (err < 0)
846 dev_err(output->dev,
847 "failed to set base clock rate to %lu Hz\n",
848 pclk * 2);
849
850 return 0;
851}
852
853static int tegra_output_hdmi_check_mode(struct tegra_output *output,
854 struct drm_display_mode *mode,
855 enum drm_mode_status *status)
856{
857 struct tegra_hdmi *hdmi = to_hdmi(output);
858 unsigned long pclk = mode->clock * 1000;
859 struct clk *parent;
860 long err;
861
862 parent = clk_get_parent(hdmi->clk_parent);
863
864 err = clk_round_rate(parent, pclk * 4);
865 if (err < 0)
866 *status = MODE_NOCLOCK;
867 else
868 *status = MODE_OK;
869
870 return 0;
871}
872
873static const struct tegra_output_ops hdmi_ops = {
874 .enable = tegra_output_hdmi_enable,
875 .disable = tegra_output_hdmi_disable,
876 .setup_clock = tegra_output_hdmi_setup_clock,
877 .check_mode = tegra_output_hdmi_check_mode,
878};
879
880static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
881{
882 struct drm_info_node *node = s->private;
883 struct tegra_hdmi *hdmi = node->info_ent->data;
884 int err;
885
886 err = clk_enable(hdmi->clk);
887 if (err)
888 return err;
889
890#define DUMP_REG(name) \
891 seq_printf(s, "%-56s %#05x %08lx\n", #name, name, \
892 tegra_hdmi_readl(hdmi, name))
893
894 DUMP_REG(HDMI_CTXSW);
895 DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
896 DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
897 DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
898 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
899 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
900 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
901 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
902 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
903 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
904 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
905 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
906 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
907 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
908 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
909 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
910 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
911 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
912 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
913 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
914 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
915 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
916 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
917 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
918 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
919 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
920 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
921 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
922 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
923 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
924 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
925 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
926 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
927 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
928 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
929 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
930 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
931 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
932 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
933 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
934 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
935 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
936 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
937 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
938 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
939 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
940 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
941 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
942 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
943 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
944 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
945 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
946 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
947 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
948 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
949 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
950 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
951 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
952 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
953 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
954 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
955 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
956 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
957 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
958 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
959 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
960 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
961 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
962 DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
963 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
964 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
965 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
966 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
967 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
968 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
969 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
970 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
971 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
972 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
973 DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
974 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
975 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
976 DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL);
977 DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
978 DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
979 DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
980 DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
981 DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
982 DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
983 DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
984 DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
985 DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
986 DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
987 DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
988 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
989 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0));
990 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1));
991 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2));
992 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3));
993 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4));
994 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5));
995 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6));
996 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7));
997 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8));
998 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9));
999 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10));
1000 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11));
1001 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12));
1002 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13));
1003 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14));
1004 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15));
1005 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
1006 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
1007 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
1008 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
1009 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
1010 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
1011 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
1012 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
1013 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
1014 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
1015 DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
1016 DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
1017 DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
1018 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
1019 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
1020 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
1021 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
1022 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
1023 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
1024 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
1025 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
1026 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
1027 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
1028 DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
1029 DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
1030 DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
1031 DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
1032 DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
1033 DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
1034 DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
1035 DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
1036 DUMP_REG(HDMI_NV_PDISP_SCRATCH);
1037 DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
1038 DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
1039 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
1040 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
1041 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
1042 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
1043 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
1044 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
1045 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
1046 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
1047 DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
1048 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
1049 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
1050 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
1051
1052#undef DUMP_REG
1053
1054 clk_disable(hdmi->clk);
1055
1056 return 0;
1057}
1058
1059static struct drm_info_list debugfs_files[] = {
1060 { "regs", tegra_hdmi_show_regs, 0, NULL },
1061};
1062
1063static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi,
1064 struct drm_minor *minor)
1065{
1066 unsigned int i;
1067 int err;
1068
1069 hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root);
1070 if (!hdmi->debugfs)
1071 return -ENOMEM;
1072
1073 hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1074 GFP_KERNEL);
1075 if (!hdmi->debugfs_files) {
1076 err = -ENOMEM;
1077 goto remove;
1078 }
1079
1080 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1081 hdmi->debugfs_files[i].data = hdmi;
1082
1083 err = drm_debugfs_create_files(hdmi->debugfs_files,
1084 ARRAY_SIZE(debugfs_files),
1085 hdmi->debugfs, minor);
1086 if (err < 0)
1087 goto free;
1088
1089 hdmi->minor = minor;
1090
1091 return 0;
1092
1093free:
1094 kfree(hdmi->debugfs_files);
1095 hdmi->debugfs_files = NULL;
1096remove:
1097 debugfs_remove(hdmi->debugfs);
1098 hdmi->debugfs = NULL;
1099
1100 return err;
1101}
1102
1103static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
1104{
1105 drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files),
1106 hdmi->minor);
1107 hdmi->minor = NULL;
1108
1109 kfree(hdmi->debugfs_files);
1110 hdmi->debugfs_files = NULL;
1111
1112 debugfs_remove(hdmi->debugfs);
1113 hdmi->debugfs = NULL;
1114
1115 return 0;
1116}
1117
1118static int tegra_hdmi_init(struct host1x_client *client)
1119{
1120 struct tegra_drm *tegra = dev_get_drvdata(client->parent);
1121 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1122 int err;
1123
1124 hdmi->output.type = TEGRA_OUTPUT_HDMI;
1125 hdmi->output.dev = client->dev;
1126 hdmi->output.ops = &hdmi_ops;
1127
1128 err = tegra_output_init(tegra->drm, &hdmi->output);
1129 if (err < 0) {
1130 dev_err(client->dev, "output setup failed: %d\n", err);
1131 return err;
1132 }
1133
1134 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1135 err = tegra_hdmi_debugfs_init(hdmi, tegra->drm->primary);
1136 if (err < 0)
1137 dev_err(client->dev, "debugfs setup failed: %d\n", err);
1138 }
1139
1140 return 0;
1141}
1142
1143static int tegra_hdmi_exit(struct host1x_client *client)
1144{
1145 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1146 int err;
1147
1148 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1149 err = tegra_hdmi_debugfs_exit(hdmi);
1150 if (err < 0)
1151 dev_err(client->dev, "debugfs cleanup failed: %d\n",
1152 err);
1153 }
1154
1155 err = tegra_output_disable(&hdmi->output);
1156 if (err < 0) {
1157 dev_err(client->dev, "output failed to disable: %d\n", err);
1158 return err;
1159 }
1160
1161 err = tegra_output_exit(&hdmi->output);
1162 if (err < 0) {
1163 dev_err(client->dev, "output cleanup failed: %d\n", err);
1164 return err;
1165 }
1166
1167 return 0;
1168}
1169
1170static const struct host1x_client_ops hdmi_client_ops = {
1171 .init = tegra_hdmi_init,
1172 .exit = tegra_hdmi_exit,
1173};
1174
1175static int tegra_hdmi_probe(struct platform_device *pdev)
1176{
1177 struct tegra_hdmi *hdmi;
1178 struct resource *regs;
1179 int err;
1180
1181 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
1182 if (!hdmi)
1183 return -ENOMEM;
1184
1185 hdmi->dev = &pdev->dev;
1186 hdmi->audio_source = AUTO;
1187 hdmi->audio_freq = 44100;
1188 hdmi->stereo = false;
1189 hdmi->dvi = false;
1190
1191 hdmi->clk = devm_clk_get(&pdev->dev, NULL);
1192 if (IS_ERR(hdmi->clk)) {
1193 dev_err(&pdev->dev, "failed to get clock\n");
1194 return PTR_ERR(hdmi->clk);
1195 }
1196
1197 err = clk_prepare(hdmi->clk);
1198 if (err < 0)
1199 return err;
1200
1201 hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1202 if (IS_ERR(hdmi->clk_parent))
1203 return PTR_ERR(hdmi->clk_parent);
1204
1205 err = clk_prepare(hdmi->clk_parent);
1206 if (err < 0)
1207 return err;
1208
1209 err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
1210 if (err < 0) {
1211 dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
1212 return err;
1213 }
1214
1215 hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
1216 if (IS_ERR(hdmi->vdd)) {
1217 dev_err(&pdev->dev, "failed to get VDD regulator\n");
1218 return PTR_ERR(hdmi->vdd);
1219 }
1220
1221 hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
1222 if (IS_ERR(hdmi->pll)) {
1223 dev_err(&pdev->dev, "failed to get PLL regulator\n");
1224 return PTR_ERR(hdmi->pll);
1225 }
1226
1227 hdmi->output.dev = &pdev->dev;
1228
1229 err = tegra_output_parse_dt(&hdmi->output);
1230 if (err < 0)
1231 return err;
1232
1233 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1234 if (!regs)
1235 return -ENXIO;
1236
1237 hdmi->regs = devm_ioremap_resource(&pdev->dev, regs);
1238 if (IS_ERR(hdmi->regs))
1239 return PTR_ERR(hdmi->regs);
1240
1241 err = platform_get_irq(pdev, 0);
1242 if (err < 0)
1243 return err;
1244
1245 hdmi->irq = err;
1246
1247 INIT_LIST_HEAD(&hdmi->client.list);
1248 hdmi->client.ops = &hdmi_client_ops;
1249 hdmi->client.dev = &pdev->dev;
1250
1251 err = host1x_client_register(&hdmi->client);
1252 if (err < 0) {
1253 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1254 err);
1255 return err;
1256 }
1257
1258 platform_set_drvdata(pdev, hdmi);
1259
1260 return 0;
1261}
1262
1263static int tegra_hdmi_remove(struct platform_device *pdev)
1264{
1265 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
1266 int err;
1267
1268 err = host1x_client_unregister(&hdmi->client);
1269 if (err < 0) {
1270 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1271 err);
1272 return err;
1273 }
1274
1275 clk_unprepare(hdmi->clk_parent);
1276 clk_unprepare(hdmi->clk);
1277
1278 return 0;
1279}
1280
1281static struct of_device_id tegra_hdmi_of_match[] = {
1282 { .compatible = "nvidia,tegra30-hdmi", },
1283 { .compatible = "nvidia,tegra20-hdmi", },
1284 { },
1285};
1286
1287struct platform_driver tegra_hdmi_driver = {
1288 .driver = {
1289 .name = "tegra-hdmi",
1290 .owner = THIS_MODULE,
1291 .of_match_table = tegra_hdmi_of_match,
1292 },
1293 .probe = tegra_hdmi_probe,
1294 .remove = tegra_hdmi_remove,
1295};
diff --git a/drivers/gpu/host1x/drm/hdmi.h b/drivers/gpu/host1x/drm/hdmi.h
deleted file mode 100644
index 52ac36e08ccb..000000000000
--- a/drivers/gpu/host1x/drm/hdmi.h
+++ /dev/null
@@ -1,386 +0,0 @@
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/output.c b/drivers/gpu/host1x/drm/output.c
deleted file mode 100644
index 8f40fa646cec..000000000000
--- a/drivers/gpu/host1x/drm/output.c
+++ /dev/null
@@ -1,270 +0,0 @@
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/of_gpio.h>
11
12#include "drm.h"
13
14static int tegra_connector_get_modes(struct drm_connector *connector)
15{
16 struct tegra_output *output = connector_to_output(connector);
17 struct edid *edid = NULL;
18 int err = 0;
19
20 if (output->edid)
21 edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
22 else if (output->ddc)
23 edid = drm_get_edid(connector, output->ddc);
24
25 drm_mode_connector_update_edid_property(connector, edid);
26
27 if (edid) {
28 err = drm_add_edid_modes(connector, edid);
29 kfree(edid);
30 }
31
32 return err;
33}
34
35static int tegra_connector_mode_valid(struct drm_connector *connector,
36 struct drm_display_mode *mode)
37{
38 struct tegra_output *output = connector_to_output(connector);
39 enum drm_mode_status status = MODE_OK;
40 int err;
41
42 err = tegra_output_check_mode(output, mode, &status);
43 if (err < 0)
44 return MODE_ERROR;
45
46 return status;
47}
48
49static struct drm_encoder *
50tegra_connector_best_encoder(struct drm_connector *connector)
51{
52 struct tegra_output *output = connector_to_output(connector);
53
54 return &output->encoder;
55}
56
57static const struct drm_connector_helper_funcs connector_helper_funcs = {
58 .get_modes = tegra_connector_get_modes,
59 .mode_valid = tegra_connector_mode_valid,
60 .best_encoder = tegra_connector_best_encoder,
61};
62
63static enum drm_connector_status
64tegra_connector_detect(struct drm_connector *connector, bool force)
65{
66 struct tegra_output *output = connector_to_output(connector);
67 enum drm_connector_status status = connector_status_unknown;
68
69 if (gpio_is_valid(output->hpd_gpio)) {
70 if (gpio_get_value(output->hpd_gpio) == 0)
71 status = connector_status_disconnected;
72 else
73 status = connector_status_connected;
74 } else {
75 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
76 status = connector_status_connected;
77 }
78
79 return status;
80}
81
82static void tegra_connector_destroy(struct drm_connector *connector)
83{
84 drm_sysfs_connector_remove(connector);
85 drm_connector_cleanup(connector);
86}
87
88static const struct drm_connector_funcs connector_funcs = {
89 .dpms = drm_helper_connector_dpms,
90 .detect = tegra_connector_detect,
91 .fill_modes = drm_helper_probe_single_connector_modes,
92 .destroy = tegra_connector_destroy,
93};
94
95static void tegra_encoder_destroy(struct drm_encoder *encoder)
96{
97 drm_encoder_cleanup(encoder);
98}
99
100static const struct drm_encoder_funcs encoder_funcs = {
101 .destroy = tegra_encoder_destroy,
102};
103
104static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
105{
106}
107
108static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
109 const struct drm_display_mode *mode,
110 struct drm_display_mode *adjusted)
111{
112 return true;
113}
114
115static void tegra_encoder_prepare(struct drm_encoder *encoder)
116{
117}
118
119static void tegra_encoder_commit(struct drm_encoder *encoder)
120{
121}
122
123static void tegra_encoder_mode_set(struct drm_encoder *encoder,
124 struct drm_display_mode *mode,
125 struct drm_display_mode *adjusted)
126{
127 struct tegra_output *output = encoder_to_output(encoder);
128 int err;
129
130 err = tegra_output_enable(output);
131 if (err < 0)
132 dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err);
133}
134
135static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
136 .dpms = tegra_encoder_dpms,
137 .mode_fixup = tegra_encoder_mode_fixup,
138 .prepare = tegra_encoder_prepare,
139 .commit = tegra_encoder_commit,
140 .mode_set = tegra_encoder_mode_set,
141};
142
143static irqreturn_t hpd_irq(int irq, void *data)
144{
145 struct tegra_output *output = data;
146
147 drm_helper_hpd_irq_event(output->connector.dev);
148
149 return IRQ_HANDLED;
150}
151
152int tegra_output_parse_dt(struct tegra_output *output)
153{
154 enum of_gpio_flags flags;
155 struct device_node *ddc;
156 size_t size;
157 int err;
158
159 if (!output->of_node)
160 output->of_node = output->dev->of_node;
161
162 output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
163
164 ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
165 if (ddc) {
166 output->ddc = of_find_i2c_adapter_by_node(ddc);
167 if (!output->ddc) {
168 err = -EPROBE_DEFER;
169 of_node_put(ddc);
170 return err;
171 }
172
173 of_node_put(ddc);
174 }
175
176 if (!output->edid && !output->ddc)
177 return -ENODEV;
178
179 output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
180 "nvidia,hpd-gpio", 0,
181 &flags);
182
183 return 0;
184}
185
186int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
187{
188 int connector, encoder, err;
189
190 if (gpio_is_valid(output->hpd_gpio)) {
191 unsigned long flags;
192
193 err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN,
194 "HDMI hotplug detect");
195 if (err < 0) {
196 dev_err(output->dev, "gpio_request_one(): %d\n", err);
197 return err;
198 }
199
200 err = gpio_to_irq(output->hpd_gpio);
201 if (err < 0) {
202 dev_err(output->dev, "gpio_to_irq(): %d\n", err);
203 goto free_hpd;
204 }
205
206 output->hpd_irq = err;
207
208 flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
209 IRQF_ONESHOT;
210
211 err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
212 flags, "hpd", output);
213 if (err < 0) {
214 dev_err(output->dev, "failed to request IRQ#%u: %d\n",
215 output->hpd_irq, err);
216 goto free_hpd;
217 }
218
219 output->connector.polled = DRM_CONNECTOR_POLL_HPD;
220 }
221
222 switch (output->type) {
223 case TEGRA_OUTPUT_RGB:
224 connector = DRM_MODE_CONNECTOR_LVDS;
225 encoder = DRM_MODE_ENCODER_LVDS;
226 break;
227
228 case TEGRA_OUTPUT_HDMI:
229 connector = DRM_MODE_CONNECTOR_HDMIA;
230 encoder = DRM_MODE_ENCODER_TMDS;
231 break;
232
233 default:
234 connector = DRM_MODE_CONNECTOR_Unknown;
235 encoder = DRM_MODE_ENCODER_NONE;
236 break;
237 }
238
239 drm_connector_init(drm, &output->connector, &connector_funcs,
240 connector);
241 drm_connector_helper_add(&output->connector, &connector_helper_funcs);
242
243 drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
244 drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
245
246 drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
247 drm_sysfs_connector_add(&output->connector);
248
249 output->encoder.possible_crtcs = 0x3;
250
251 return 0;
252
253free_hpd:
254 gpio_free(output->hpd_gpio);
255
256 return err;
257}
258
259int tegra_output_exit(struct tegra_output *output)
260{
261 if (gpio_is_valid(output->hpd_gpio)) {
262 free_irq(output->hpd_irq, output);
263 gpio_free(output->hpd_gpio);
264 }
265
266 if (output->ddc)
267 put_device(&output->ddc->dev);
268
269 return 0;
270}
diff --git a/drivers/gpu/host1x/drm/rgb.c b/drivers/gpu/host1x/drm/rgb.c
deleted file mode 100644
index e4d28411973d..000000000000
--- a/drivers/gpu/host1x/drm/rgb.c
+++ /dev/null
@@ -1,225 +0,0 @@
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
12#include "drm.h"
13#include "dc.h"
14
15struct tegra_rgb {
16 struct tegra_output output;
17 struct clk *clk_parent;
18 struct clk *clk;
19};
20
21static inline struct tegra_rgb *to_rgb(struct tegra_output *output)
22{
23 return container_of(output, struct tegra_rgb, output);
24}
25
26struct reg_entry {
27 unsigned long offset;
28 unsigned long value;
29};
30
31static const struct reg_entry rgb_enable[] = {
32 { DC_COM_PIN_OUTPUT_ENABLE(0), 0x00000000 },
33 { DC_COM_PIN_OUTPUT_ENABLE(1), 0x00000000 },
34 { DC_COM_PIN_OUTPUT_ENABLE(2), 0x00000000 },
35 { DC_COM_PIN_OUTPUT_ENABLE(3), 0x00000000 },
36 { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
37 { DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 },
38 { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
39 { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
40 { DC_COM_PIN_OUTPUT_DATA(0), 0x00000000 },
41 { DC_COM_PIN_OUTPUT_DATA(1), 0x00000000 },
42 { DC_COM_PIN_OUTPUT_DATA(2), 0x00000000 },
43 { DC_COM_PIN_OUTPUT_DATA(3), 0x00000000 },
44 { DC_COM_PIN_OUTPUT_SELECT(0), 0x00000000 },
45 { DC_COM_PIN_OUTPUT_SELECT(1), 0x00000000 },
46 { DC_COM_PIN_OUTPUT_SELECT(2), 0x00000000 },
47 { DC_COM_PIN_OUTPUT_SELECT(3), 0x00000000 },
48 { DC_COM_PIN_OUTPUT_SELECT(4), 0x00210222 },
49 { DC_COM_PIN_OUTPUT_SELECT(5), 0x00002200 },
50 { DC_COM_PIN_OUTPUT_SELECT(6), 0x00020000 },
51};
52
53static const struct reg_entry rgb_disable[] = {
54 { DC_COM_PIN_OUTPUT_SELECT(6), 0x00000000 },
55 { DC_COM_PIN_OUTPUT_SELECT(5), 0x00000000 },
56 { DC_COM_PIN_OUTPUT_SELECT(4), 0x00000000 },
57 { DC_COM_PIN_OUTPUT_SELECT(3), 0x00000000 },
58 { DC_COM_PIN_OUTPUT_SELECT(2), 0x00000000 },
59 { DC_COM_PIN_OUTPUT_SELECT(1), 0x00000000 },
60 { DC_COM_PIN_OUTPUT_SELECT(0), 0x00000000 },
61 { DC_COM_PIN_OUTPUT_DATA(3), 0xaaaaaaaa },
62 { DC_COM_PIN_OUTPUT_DATA(2), 0xaaaaaaaa },
63 { DC_COM_PIN_OUTPUT_DATA(1), 0xaaaaaaaa },
64 { DC_COM_PIN_OUTPUT_DATA(0), 0xaaaaaaaa },
65 { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
66 { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
67 { DC_COM_PIN_OUTPUT_POLARITY(1), 0x00000000 },
68 { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
69 { DC_COM_PIN_OUTPUT_ENABLE(3), 0x55555555 },
70 { DC_COM_PIN_OUTPUT_ENABLE(2), 0x55555555 },
71 { DC_COM_PIN_OUTPUT_ENABLE(1), 0x55150005 },
72 { DC_COM_PIN_OUTPUT_ENABLE(0), 0x55555555 },
73};
74
75static void tegra_dc_write_regs(struct tegra_dc *dc,
76 const struct reg_entry *table,
77 unsigned int num)
78{
79 unsigned int i;
80
81 for (i = 0; i < num; i++)
82 tegra_dc_writel(dc, table[i].value, table[i].offset);
83}
84
85static int tegra_output_rgb_enable(struct tegra_output *output)
86{
87 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
88
89 tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
90
91 return 0;
92}
93
94static int tegra_output_rgb_disable(struct tegra_output *output)
95{
96 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
97
98 tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
99
100 return 0;
101}
102
103static int tegra_output_rgb_setup_clock(struct tegra_output *output,
104 struct clk *clk, unsigned long pclk)
105{
106 struct tegra_rgb *rgb = to_rgb(output);
107
108 return clk_set_parent(clk, rgb->clk_parent);
109}
110
111static int tegra_output_rgb_check_mode(struct tegra_output *output,
112 struct drm_display_mode *mode,
113 enum drm_mode_status *status)
114{
115 /*
116 * FIXME: For now, always assume that the mode is okay. There are
117 * unresolved issues with clk_round_rate(), which doesn't always
118 * reliably report whether a frequency can be set or not.
119 */
120
121 *status = MODE_OK;
122
123 return 0;
124}
125
126static const struct tegra_output_ops rgb_ops = {
127 .enable = tegra_output_rgb_enable,
128 .disable = tegra_output_rgb_disable,
129 .setup_clock = tegra_output_rgb_setup_clock,
130 .check_mode = tegra_output_rgb_check_mode,
131};
132
133int tegra_dc_rgb_probe(struct tegra_dc *dc)
134{
135 struct device_node *np;
136 struct tegra_rgb *rgb;
137 int err;
138
139 np = of_get_child_by_name(dc->dev->of_node, "rgb");
140 if (!np || !of_device_is_available(np))
141 return -ENODEV;
142
143 rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL);
144 if (!rgb)
145 return -ENOMEM;
146
147 rgb->output.dev = dc->dev;
148 rgb->output.of_node = np;
149
150 err = tegra_output_parse_dt(&rgb->output);
151 if (err < 0)
152 return err;
153
154 rgb->clk = devm_clk_get(dc->dev, NULL);
155 if (IS_ERR(rgb->clk)) {
156 dev_err(dc->dev, "failed to get clock\n");
157 return PTR_ERR(rgb->clk);
158 }
159
160 rgb->clk_parent = devm_clk_get(dc->dev, "parent");
161 if (IS_ERR(rgb->clk_parent)) {
162 dev_err(dc->dev, "failed to get parent clock\n");
163 return PTR_ERR(rgb->clk_parent);
164 }
165
166 err = clk_set_parent(rgb->clk, rgb->clk_parent);
167 if (err < 0) {
168 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
169 return err;
170 }
171
172 dc->rgb = &rgb->output;
173
174 return 0;
175}
176
177int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
178{
179 struct tegra_rgb *rgb = to_rgb(dc->rgb);
180 int err;
181
182 if (!dc->rgb)
183 return -ENODEV;
184
185 rgb->output.type = TEGRA_OUTPUT_RGB;
186 rgb->output.ops = &rgb_ops;
187
188 err = tegra_output_init(dc->base.dev, &rgb->output);
189 if (err < 0) {
190 dev_err(dc->dev, "output setup failed: %d\n", err);
191 return err;
192 }
193
194 /*
195 * By default, outputs can be associated with each display controller.
196 * RGB outputs are an exception, so we make sure they can be attached
197 * to only their parent display controller.
198 */
199 rgb->output.encoder.possible_crtcs = 1 << dc->pipe;
200
201 return 0;
202}
203
204int tegra_dc_rgb_exit(struct tegra_dc *dc)
205{
206 if (dc->rgb) {
207 int err;
208
209 err = tegra_output_disable(dc->rgb);
210 if (err < 0) {
211 dev_err(dc->dev, "output failed to disable: %d\n", err);
212 return err;
213 }
214
215 err = tegra_output_exit(dc->rgb);
216 if (err < 0) {
217 dev_err(dc->dev, "output cleanup failed: %d\n", err);
218 return err;
219 }
220
221 dc->rgb = NULL;
222 }
223
224 return 0;
225}