[go: nahoru, domu]

1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/clk.h>
11#include <linux/debugfs.h>
12#include <linux/reset.h>
13
14#include "dc.h"
15#include "drm.h"
16#include "gem.h"
17
18struct tegra_dc_soc_info {
19	bool supports_interlacing;
20	bool supports_cursor;
21	bool supports_block_linear;
22	unsigned int pitch_align;
23};
24
25struct tegra_plane {
26	struct drm_plane base;
27	unsigned int index;
28};
29
30static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
31{
32	return container_of(plane, struct tegra_plane, base);
33}
34
35static unsigned int tegra_dc_format(uint32_t format, uint32_t *swap)
36{
37	/* assume no swapping of fetched data */
38	if (swap)
39		*swap = BYTE_SWAP_NOSWAP;
40
41	switch (format) {
42	case DRM_FORMAT_XBGR8888:
43		return WIN_COLOR_DEPTH_R8G8B8A8;
44
45	case DRM_FORMAT_XRGB8888:
46		return WIN_COLOR_DEPTH_B8G8R8A8;
47
48	case DRM_FORMAT_RGB565:
49		return WIN_COLOR_DEPTH_B5G6R5;
50
51	case DRM_FORMAT_UYVY:
52		return WIN_COLOR_DEPTH_YCbCr422;
53
54	case DRM_FORMAT_YUYV:
55		if (swap)
56			*swap = BYTE_SWAP_SWAP2;
57
58		return WIN_COLOR_DEPTH_YCbCr422;
59
60	case DRM_FORMAT_YUV420:
61		return WIN_COLOR_DEPTH_YCbCr420P;
62
63	case DRM_FORMAT_YUV422:
64		return WIN_COLOR_DEPTH_YCbCr422P;
65
66	default:
67		break;
68	}
69
70	WARN(1, "unsupported pixel format %u, using default\n", format);
71	return WIN_COLOR_DEPTH_B8G8R8A8;
72}
73
74static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
75{
76	switch (format) {
77	case WIN_COLOR_DEPTH_YCbCr422:
78	case WIN_COLOR_DEPTH_YUV422:
79		if (planar)
80			*planar = false;
81
82		return true;
83
84	case WIN_COLOR_DEPTH_YCbCr420P:
85	case WIN_COLOR_DEPTH_YUV420P:
86	case WIN_COLOR_DEPTH_YCbCr422P:
87	case WIN_COLOR_DEPTH_YUV422P:
88	case WIN_COLOR_DEPTH_YCbCr422R:
89	case WIN_COLOR_DEPTH_YUV422R:
90	case WIN_COLOR_DEPTH_YCbCr422RA:
91	case WIN_COLOR_DEPTH_YUV422RA:
92		if (planar)
93			*planar = true;
94
95		return true;
96	}
97
98	return false;
99}
100
101static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
102				  unsigned int bpp)
103{
104	fixed20_12 outf = dfixed_init(out);
105	fixed20_12 inf = dfixed_init(in);
106	u32 dda_inc;
107	int max;
108
109	if (v)
110		max = 15;
111	else {
112		switch (bpp) {
113		case 2:
114			max = 8;
115			break;
116
117		default:
118			WARN_ON_ONCE(1);
119			/* fallthrough */
120		case 4:
121			max = 4;
122			break;
123		}
124	}
125
126	outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
127	inf.full -= dfixed_const(1);
128
129	dda_inc = dfixed_div(inf, outf);
130	dda_inc = min_t(u32, dda_inc, dfixed_const(max));
131
132	return dda_inc;
133}
134
135static inline u32 compute_initial_dda(unsigned int in)
136{
137	fixed20_12 inf = dfixed_init(in);
138	return dfixed_frac(inf);
139}
140
141static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
142				 const struct tegra_dc_window *window)
143{
144	unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
145	unsigned long value;
146	bool yuv, planar;
147
148	/*
149	 * For YUV planar modes, the number of bytes per pixel takes into
150	 * account only the luma component and therefore is 1.
151	 */
152	yuv = tegra_dc_format_is_yuv(window->format, &planar);
153	if (!yuv)
154		bpp = window->bits_per_pixel / 8;
155	else
156		bpp = planar ? 1 : 2;
157
158	value = WINDOW_A_SELECT << index;
159	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
160
161	tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
162	tegra_dc_writel(dc, window->swap, DC_WIN_BYTE_SWAP);
163
164	value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
165	tegra_dc_writel(dc, value, DC_WIN_POSITION);
166
167	value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
168	tegra_dc_writel(dc, value, DC_WIN_SIZE);
169
170	h_offset = window->src.x * bpp;
171	v_offset = window->src.y;
172	h_size = window->src.w * bpp;
173	v_size = window->src.h;
174
175	value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
176	tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
177
178	/*
179	 * For DDA computations the number of bytes per pixel for YUV planar
180	 * modes needs to take into account all Y, U and V components.
181	 */
182	if (yuv && planar)
183		bpp = 2;
184
185	h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
186	v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
187
188	value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
189	tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
190
191	h_dda = compute_initial_dda(window->src.x);
192	v_dda = compute_initial_dda(window->src.y);
193
194	tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
195	tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
196
197	tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
198	tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
199
200	tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
201
202	if (yuv && planar) {
203		tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
204		tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
205		value = window->stride[1] << 16 | window->stride[0];
206		tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
207	} else {
208		tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
209	}
210
211	if (window->bottom_up)
212		v_offset += window->src.h - 1;
213
214	tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
215	tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
216
217	if (dc->soc->supports_block_linear) {
218		unsigned long height = window->tiling.value;
219
220		switch (window->tiling.mode) {
221		case TEGRA_BO_TILING_MODE_PITCH:
222			value = DC_WINBUF_SURFACE_KIND_PITCH;
223			break;
224
225		case TEGRA_BO_TILING_MODE_TILED:
226			value = DC_WINBUF_SURFACE_KIND_TILED;
227			break;
228
229		case TEGRA_BO_TILING_MODE_BLOCK:
230			value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
231				DC_WINBUF_SURFACE_KIND_BLOCK;
232			break;
233		}
234
235		tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
236	} else {
237		switch (window->tiling.mode) {
238		case TEGRA_BO_TILING_MODE_PITCH:
239			value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
240				DC_WIN_BUFFER_ADDR_MODE_LINEAR;
241			break;
242
243		case TEGRA_BO_TILING_MODE_TILED:
244			value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
245				DC_WIN_BUFFER_ADDR_MODE_TILE;
246			break;
247
248		case TEGRA_BO_TILING_MODE_BLOCK:
249			DRM_ERROR("hardware doesn't support block linear mode\n");
250			return -EINVAL;
251		}
252
253		tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
254	}
255
256	value = WIN_ENABLE;
257
258	if (yuv) {
259		/* setup default colorspace conversion coefficients */
260		tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
261		tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
262		tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
263		tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
264		tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
265		tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
266		tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
267		tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
268
269		value |= CSC_ENABLE;
270	} else if (window->bits_per_pixel < 24) {
271		value |= COLOR_EXPAND;
272	}
273
274	if (window->bottom_up)
275		value |= V_DIRECTION;
276
277	tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
278
279	/*
280	 * Disable blending and assume Window A is the bottom-most window,
281	 * Window C is the top-most window and Window B is in the middle.
282	 */
283	tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
284	tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
285
286	switch (index) {
287	case 0:
288		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
289		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
290		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
291		break;
292
293	case 1:
294		tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
295		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
296		tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
297		break;
298
299	case 2:
300		tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
301		tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
302		tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
303		break;
304	}
305
306	tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL);
307	tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL);
308
309	return 0;
310}
311
312static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
313			      struct drm_framebuffer *fb, int crtc_x,
314			      int crtc_y, unsigned int crtc_w,
315			      unsigned int crtc_h, uint32_t src_x,
316			      uint32_t src_y, uint32_t src_w, uint32_t src_h)
317{
318	struct tegra_plane *p = to_tegra_plane(plane);
319	struct tegra_dc *dc = to_tegra_dc(crtc);
320	struct tegra_dc_window window;
321	unsigned int i;
322	int err;
323
324	memset(&window, 0, sizeof(window));
325	window.src.x = src_x >> 16;
326	window.src.y = src_y >> 16;
327	window.src.w = src_w >> 16;
328	window.src.h = src_h >> 16;
329	window.dst.x = crtc_x;
330	window.dst.y = crtc_y;
331	window.dst.w = crtc_w;
332	window.dst.h = crtc_h;
333	window.format = tegra_dc_format(fb->pixel_format, &window.swap);
334	window.bits_per_pixel = fb->bits_per_pixel;
335	window.bottom_up = tegra_fb_is_bottom_up(fb);
336
337	err = tegra_fb_get_tiling(fb, &window.tiling);
338	if (err < 0)
339		return err;
340
341	for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
342		struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
343
344		window.base[i] = bo->paddr + fb->offsets[i];
345
346		/*
347		 * Tegra doesn't support different strides for U and V planes
348		 * so we display a warning if the user tries to display a
349		 * framebuffer with such a configuration.
350		 */
351		if (i >= 2) {
352			if (fb->pitches[i] != window.stride[1])
353				DRM_ERROR("unsupported UV-plane configuration\n");
354		} else {
355			window.stride[i] = fb->pitches[i];
356		}
357	}
358
359	return tegra_dc_setup_window(dc, p->index, &window);
360}
361
362static int tegra_plane_disable(struct drm_plane *plane)
363{
364	struct tegra_dc *dc = to_tegra_dc(plane->crtc);
365	struct tegra_plane *p = to_tegra_plane(plane);
366	unsigned long value;
367
368	if (!plane->crtc)
369		return 0;
370
371	value = WINDOW_A_SELECT << p->index;
372	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
373
374	value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
375	value &= ~WIN_ENABLE;
376	tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
377
378	tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL);
379	tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL);
380
381	return 0;
382}
383
384static void tegra_plane_destroy(struct drm_plane *plane)
385{
386	struct tegra_plane *p = to_tegra_plane(plane);
387
388	tegra_plane_disable(plane);
389	drm_plane_cleanup(plane);
390	kfree(p);
391}
392
393static const struct drm_plane_funcs tegra_plane_funcs = {
394	.update_plane = tegra_plane_update,
395	.disable_plane = tegra_plane_disable,
396	.destroy = tegra_plane_destroy,
397};
398
399static const uint32_t plane_formats[] = {
400	DRM_FORMAT_XBGR8888,
401	DRM_FORMAT_XRGB8888,
402	DRM_FORMAT_RGB565,
403	DRM_FORMAT_UYVY,
404	DRM_FORMAT_YUYV,
405	DRM_FORMAT_YUV420,
406	DRM_FORMAT_YUV422,
407};
408
409static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
410{
411	unsigned int i;
412	int err = 0;
413
414	for (i = 0; i < 2; i++) {
415		struct tegra_plane *plane;
416
417		plane = kzalloc(sizeof(*plane), GFP_KERNEL);
418		if (!plane)
419			return -ENOMEM;
420
421		plane->index = 1 + i;
422
423		err = drm_plane_init(drm, &plane->base, 1 << dc->pipe,
424				     &tegra_plane_funcs, plane_formats,
425				     ARRAY_SIZE(plane_formats), false);
426		if (err < 0) {
427			kfree(plane);
428			return err;
429		}
430	}
431
432	return 0;
433}
434
435static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
436			     struct drm_framebuffer *fb)
437{
438	struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
439	unsigned int h_offset = 0, v_offset = 0;
440	struct tegra_bo_tiling tiling;
441	unsigned int format, swap;
442	unsigned long value;
443	int err;
444
445	err = tegra_fb_get_tiling(fb, &tiling);
446	if (err < 0)
447		return err;
448
449	tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
450
451	value = fb->offsets[0] + y * fb->pitches[0] +
452		x * fb->bits_per_pixel / 8;
453
454	tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR);
455	tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
456
457	format = tegra_dc_format(fb->pixel_format, &swap);
458	tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
459	tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
460
461	if (dc->soc->supports_block_linear) {
462		unsigned long height = tiling.value;
463
464		switch (tiling.mode) {
465		case TEGRA_BO_TILING_MODE_PITCH:
466			value = DC_WINBUF_SURFACE_KIND_PITCH;
467			break;
468
469		case TEGRA_BO_TILING_MODE_TILED:
470			value = DC_WINBUF_SURFACE_KIND_TILED;
471			break;
472
473		case TEGRA_BO_TILING_MODE_BLOCK:
474			value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
475				DC_WINBUF_SURFACE_KIND_BLOCK;
476			break;
477		}
478
479		tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
480	} else {
481		switch (tiling.mode) {
482		case TEGRA_BO_TILING_MODE_PITCH:
483			value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
484				DC_WIN_BUFFER_ADDR_MODE_LINEAR;
485			break;
486
487		case TEGRA_BO_TILING_MODE_TILED:
488			value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
489				DC_WIN_BUFFER_ADDR_MODE_TILE;
490			break;
491
492		case TEGRA_BO_TILING_MODE_BLOCK:
493			DRM_ERROR("hardware doesn't support block linear mode\n");
494			return -EINVAL;
495		}
496
497		tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
498	}
499
500	/* make sure bottom-up buffers are properly displayed */
501	if (tegra_fb_is_bottom_up(fb)) {
502		value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
503		value |= V_DIRECTION;
504		tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
505
506		v_offset += fb->height - 1;
507	} else {
508		value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
509		value &= ~V_DIRECTION;
510		tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
511	}
512
513	tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
514	tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
515
516	value = GENERAL_UPDATE | WIN_A_UPDATE;
517	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
518
519	value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
520	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
521
522	return 0;
523}
524
525void tegra_dc_enable_vblank(struct tegra_dc *dc)
526{
527	unsigned long value, flags;
528
529	spin_lock_irqsave(&dc->lock, flags);
530
531	value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
532	value |= VBLANK_INT;
533	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
534
535	spin_unlock_irqrestore(&dc->lock, flags);
536}
537
538void tegra_dc_disable_vblank(struct tegra_dc *dc)
539{
540	unsigned long value, flags;
541
542	spin_lock_irqsave(&dc->lock, flags);
543
544	value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
545	value &= ~VBLANK_INT;
546	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
547
548	spin_unlock_irqrestore(&dc->lock, flags);
549}
550
551static int tegra_dc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file,
552				uint32_t handle, uint32_t width,
553				uint32_t height, int32_t hot_x, int32_t hot_y)
554{
555	unsigned long value = CURSOR_CLIP_DISPLAY;
556	struct tegra_dc *dc = to_tegra_dc(crtc);
557	struct drm_gem_object *gem;
558	struct tegra_bo *bo = NULL;
559
560	if (!dc->soc->supports_cursor)
561		return -ENXIO;
562
563	if (width != height)
564		return -EINVAL;
565
566	switch (width) {
567	case 32:
568		value |= CURSOR_SIZE_32x32;
569		break;
570
571	case 64:
572		value |= CURSOR_SIZE_64x64;
573		break;
574
575	case 128:
576		value |= CURSOR_SIZE_128x128;
577
578	case 256:
579		value |= CURSOR_SIZE_256x256;
580		break;
581
582	default:
583		return -EINVAL;
584	}
585
586	if (handle) {
587		gem = drm_gem_object_lookup(crtc->dev, file, handle);
588		if (!gem)
589			return -ENOENT;
590
591		bo = to_tegra_bo(gem);
592	}
593
594	if (bo) {
595		unsigned long addr = (bo->paddr & 0xfffffc00) >> 10;
596#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
597		unsigned long high = (bo->paddr & 0xfffffffc) >> 32;
598#endif
599
600		tegra_dc_writel(dc, value | addr, DC_DISP_CURSOR_START_ADDR);
601
602#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
603		tegra_dc_writel(dc, high, DC_DISP_CURSOR_START_ADDR_HI);
604#endif
605
606		value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
607		value |= CURSOR_ENABLE;
608		tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
609
610		value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
611		value &= ~CURSOR_DST_BLEND_MASK;
612		value &= ~CURSOR_SRC_BLEND_MASK;
613		value |= CURSOR_MODE_NORMAL;
614		value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC;
615		value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
616		value |= CURSOR_ALPHA;
617		tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
618	} else {
619		value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
620		value &= ~CURSOR_ENABLE;
621		tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
622	}
623
624	tegra_dc_writel(dc, CURSOR_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
625	tegra_dc_writel(dc, CURSOR_ACT_REQ, DC_CMD_STATE_CONTROL);
626
627	tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
628	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
629
630	return 0;
631}
632
633static int tegra_dc_cursor_move(struct drm_crtc *crtc, int x, int y)
634{
635	struct tegra_dc *dc = to_tegra_dc(crtc);
636	unsigned long value;
637
638	if (!dc->soc->supports_cursor)
639		return -ENXIO;
640
641	value = ((y & 0x3fff) << 16) | (x & 0x3fff);
642	tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
643
644	tegra_dc_writel(dc, CURSOR_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
645	tegra_dc_writel(dc, CURSOR_ACT_REQ, DC_CMD_STATE_CONTROL);
646
647	/* XXX: only required on generations earlier than Tegra124? */
648	tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
649	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
650
651	return 0;
652}
653
654static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
655{
656	struct drm_device *drm = dc->base.dev;
657	struct drm_crtc *crtc = &dc->base;
658	unsigned long flags, base;
659	struct tegra_bo *bo;
660
661	if (!dc->event)
662		return;
663
664	bo = tegra_fb_get_plane(crtc->primary->fb, 0);
665
666	/* check if new start address has been latched */
667	tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
668	base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
669	tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
670
671	if (base == bo->paddr + crtc->primary->fb->offsets[0]) {
672		spin_lock_irqsave(&drm->event_lock, flags);
673		drm_send_vblank_event(drm, dc->pipe, dc->event);
674		drm_vblank_put(drm, dc->pipe);
675		dc->event = NULL;
676		spin_unlock_irqrestore(&drm->event_lock, flags);
677	}
678}
679
680void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
681{
682	struct tegra_dc *dc = to_tegra_dc(crtc);
683	struct drm_device *drm = crtc->dev;
684	unsigned long flags;
685
686	spin_lock_irqsave(&drm->event_lock, flags);
687
688	if (dc->event && dc->event->base.file_priv == file) {
689		dc->event->base.destroy(&dc->event->base);
690		drm_vblank_put(drm, dc->pipe);
691		dc->event = NULL;
692	}
693
694	spin_unlock_irqrestore(&drm->event_lock, flags);
695}
696
697static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
698			      struct drm_pending_vblank_event *event, uint32_t page_flip_flags)
699{
700	struct tegra_dc *dc = to_tegra_dc(crtc);
701	struct drm_device *drm = crtc->dev;
702
703	if (dc->event)
704		return -EBUSY;
705
706	if (event) {
707		event->pipe = dc->pipe;
708		dc->event = event;
709		drm_vblank_get(drm, dc->pipe);
710	}
711
712	tegra_dc_set_base(dc, 0, 0, fb);
713	crtc->primary->fb = fb;
714
715	return 0;
716}
717
718static void drm_crtc_clear(struct drm_crtc *crtc)
719{
720	memset(crtc, 0, sizeof(*crtc));
721}
722
723static void tegra_dc_destroy(struct drm_crtc *crtc)
724{
725	drm_crtc_cleanup(crtc);
726	drm_crtc_clear(crtc);
727}
728
729static const struct drm_crtc_funcs tegra_crtc_funcs = {
730	.cursor_set2 = tegra_dc_cursor_set2,
731	.cursor_move = tegra_dc_cursor_move,
732	.page_flip = tegra_dc_page_flip,
733	.set_config = drm_crtc_helper_set_config,
734	.destroy = tegra_dc_destroy,
735};
736
737static void tegra_crtc_disable(struct drm_crtc *crtc)
738{
739	struct drm_device *drm = crtc->dev;
740	struct drm_plane *plane;
741
742	drm_for_each_legacy_plane(plane, &drm->mode_config.plane_list) {
743		if (plane->crtc == crtc) {
744			tegra_plane_disable(plane);
745			plane->crtc = NULL;
746
747			if (plane->fb) {
748				drm_framebuffer_unreference(plane->fb);
749				plane->fb = NULL;
750			}
751		}
752	}
753
754	drm_crtc_vblank_off(crtc);
755}
756
757static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
758				  const struct drm_display_mode *mode,
759				  struct drm_display_mode *adjusted)
760{
761	return true;
762}
763
764static int tegra_dc_set_timings(struct tegra_dc *dc,
765				struct drm_display_mode *mode)
766{
767	unsigned int h_ref_to_sync = 1;
768	unsigned int v_ref_to_sync = 1;
769	unsigned long value;
770
771	tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
772
773	value = (v_ref_to_sync << 16) | h_ref_to_sync;
774	tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
775
776	value = ((mode->vsync_end - mode->vsync_start) << 16) |
777		((mode->hsync_end - mode->hsync_start) <<  0);
778	tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
779
780	value = ((mode->vtotal - mode->vsync_end) << 16) |
781		((mode->htotal - mode->hsync_end) <<  0);
782	tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
783
784	value = ((mode->vsync_start - mode->vdisplay) << 16) |
785		((mode->hsync_start - mode->hdisplay) <<  0);
786	tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
787
788	value = (mode->vdisplay << 16) | mode->hdisplay;
789	tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
790
791	return 0;
792}
793
794static int tegra_crtc_setup_clk(struct drm_crtc *crtc,
795				struct drm_display_mode *mode)
796{
797	unsigned long pclk = mode->clock * 1000;
798	struct tegra_dc *dc = to_tegra_dc(crtc);
799	struct tegra_output *output = NULL;
800	struct drm_encoder *encoder;
801	unsigned int div;
802	u32 value;
803	long err;
804
805	list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head)
806		if (encoder->crtc == crtc) {
807			output = encoder_to_output(encoder);
808			break;
809		}
810
811	if (!output)
812		return -ENODEV;
813
814	/*
815	 * This assumes that the parent clock is pll_d_out0 or pll_d2_out
816	 * respectively, each of which divides the base pll_d by 2.
817	 */
818	err = tegra_output_setup_clock(output, dc->clk, pclk, &div);
819	if (err < 0) {
820		dev_err(dc->dev, "failed to setup clock: %ld\n", err);
821		return err;
822	}
823
824	DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk), div);
825
826	value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
827	tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
828
829	return 0;
830}
831
832static int tegra_crtc_mode_set(struct drm_crtc *crtc,
833			       struct drm_display_mode *mode,
834			       struct drm_display_mode *adjusted,
835			       int x, int y, struct drm_framebuffer *old_fb)
836{
837	struct tegra_bo *bo = tegra_fb_get_plane(crtc->primary->fb, 0);
838	struct tegra_dc *dc = to_tegra_dc(crtc);
839	struct tegra_dc_window window;
840	u32 value;
841	int err;
842
843	err = tegra_crtc_setup_clk(crtc, mode);
844	if (err) {
845		dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
846		return err;
847	}
848
849	/* program display mode */
850	tegra_dc_set_timings(dc, mode);
851
852	/* interlacing isn't supported yet, so disable it */
853	if (dc->soc->supports_interlacing) {
854		value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
855		value &= ~INTERLACE_ENABLE;
856		tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
857	}
858
859	/* setup window parameters */
860	memset(&window, 0, sizeof(window));
861	window.src.x = 0;
862	window.src.y = 0;
863	window.src.w = mode->hdisplay;
864	window.src.h = mode->vdisplay;
865	window.dst.x = 0;
866	window.dst.y = 0;
867	window.dst.w = mode->hdisplay;
868	window.dst.h = mode->vdisplay;
869	window.format = tegra_dc_format(crtc->primary->fb->pixel_format,
870					&window.swap);
871	window.bits_per_pixel = crtc->primary->fb->bits_per_pixel;
872	window.stride[0] = crtc->primary->fb->pitches[0];
873	window.base[0] = bo->paddr;
874
875	err = tegra_dc_setup_window(dc, 0, &window);
876	if (err < 0)
877		dev_err(dc->dev, "failed to enable root plane\n");
878
879	return 0;
880}
881
882static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
883				    struct drm_framebuffer *old_fb)
884{
885	struct tegra_dc *dc = to_tegra_dc(crtc);
886
887	return tegra_dc_set_base(dc, x, y, crtc->primary->fb);
888}
889
890static void tegra_crtc_prepare(struct drm_crtc *crtc)
891{
892	struct tegra_dc *dc = to_tegra_dc(crtc);
893	unsigned int syncpt;
894	unsigned long value;
895
896	drm_crtc_vblank_off(crtc);
897
898	/* hardware initialization */
899	reset_control_deassert(dc->rst);
900	usleep_range(10000, 20000);
901
902	if (dc->pipe)
903		syncpt = SYNCPT_VBLANK1;
904	else
905		syncpt = SYNCPT_VBLANK0;
906
907	/* initialize display controller */
908	tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
909	tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
910
911	value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
912	tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
913
914	value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
915		WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
916	tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
917
918	/* initialize timer */
919	value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
920		WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
921	tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
922
923	value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
924		WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
925	tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
926
927	value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
928	tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
929
930	value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
931	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
932}
933
934static void tegra_crtc_commit(struct drm_crtc *crtc)
935{
936	struct tegra_dc *dc = to_tegra_dc(crtc);
937	unsigned long value;
938
939	value = GENERAL_UPDATE | WIN_A_UPDATE;
940	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
941
942	value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
943	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
944
945	drm_crtc_vblank_on(crtc);
946}
947
948static void tegra_crtc_load_lut(struct drm_crtc *crtc)
949{
950}
951
952static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
953	.disable = tegra_crtc_disable,
954	.mode_fixup = tegra_crtc_mode_fixup,
955	.mode_set = tegra_crtc_mode_set,
956	.mode_set_base = tegra_crtc_mode_set_base,
957	.prepare = tegra_crtc_prepare,
958	.commit = tegra_crtc_commit,
959	.load_lut = tegra_crtc_load_lut,
960};
961
962static irqreturn_t tegra_dc_irq(int irq, void *data)
963{
964	struct tegra_dc *dc = data;
965	unsigned long status;
966
967	status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
968	tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
969
970	if (status & FRAME_END_INT) {
971		/*
972		dev_dbg(dc->dev, "%s(): frame end\n", __func__);
973		*/
974	}
975
976	if (status & VBLANK_INT) {
977		/*
978		dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
979		*/
980		drm_handle_vblank(dc->base.dev, dc->pipe);
981		tegra_dc_finish_page_flip(dc);
982	}
983
984	if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
985		/*
986		dev_dbg(dc->dev, "%s(): underflow\n", __func__);
987		*/
988	}
989
990	return IRQ_HANDLED;
991}
992
993static int tegra_dc_show_regs(struct seq_file *s, void *data)
994{
995	struct drm_info_node *node = s->private;
996	struct tegra_dc *dc = node->info_ent->data;
997
998#define DUMP_REG(name)						\
999	seq_printf(s, "%-40s %#05x %08lx\n", #name, name,	\
1000		   tegra_dc_readl(dc, name))
1001
1002	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT);
1003	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
1004	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR);
1005	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT);
1006	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL);
1007	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR);
1008	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT);
1009	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL);
1010	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR);
1011	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT);
1012	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL);
1013	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR);
1014	DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC);
1015	DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
1016	DUMP_REG(DC_CMD_DISPLAY_COMMAND);
1017	DUMP_REG(DC_CMD_SIGNAL_RAISE);
1018	DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
1019	DUMP_REG(DC_CMD_INT_STATUS);
1020	DUMP_REG(DC_CMD_INT_MASK);
1021	DUMP_REG(DC_CMD_INT_ENABLE);
1022	DUMP_REG(DC_CMD_INT_TYPE);
1023	DUMP_REG(DC_CMD_INT_POLARITY);
1024	DUMP_REG(DC_CMD_SIGNAL_RAISE1);
1025	DUMP_REG(DC_CMD_SIGNAL_RAISE2);
1026	DUMP_REG(DC_CMD_SIGNAL_RAISE3);
1027	DUMP_REG(DC_CMD_STATE_ACCESS);
1028	DUMP_REG(DC_CMD_STATE_CONTROL);
1029	DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
1030	DUMP_REG(DC_CMD_REG_ACT_CONTROL);
1031	DUMP_REG(DC_COM_CRC_CONTROL);
1032	DUMP_REG(DC_COM_CRC_CHECKSUM);
1033	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0));
1034	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1));
1035	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2));
1036	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3));
1037	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0));
1038	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1));
1039	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2));
1040	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3));
1041	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0));
1042	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1));
1043	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2));
1044	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3));
1045	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0));
1046	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1));
1047	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2));
1048	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3));
1049	DUMP_REG(DC_COM_PIN_INPUT_DATA(0));
1050	DUMP_REG(DC_COM_PIN_INPUT_DATA(1));
1051	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0));
1052	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1));
1053	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2));
1054	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3));
1055	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4));
1056	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5));
1057	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6));
1058	DUMP_REG(DC_COM_PIN_MISC_CONTROL);
1059	DUMP_REG(DC_COM_PIN_PM0_CONTROL);
1060	DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE);
1061	DUMP_REG(DC_COM_PIN_PM1_CONTROL);
1062	DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE);
1063	DUMP_REG(DC_COM_SPI_CONTROL);
1064	DUMP_REG(DC_COM_SPI_START_BYTE);
1065	DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB);
1066	DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD);
1067	DUMP_REG(DC_COM_HSPI_CS_DC);
1068	DUMP_REG(DC_COM_SCRATCH_REGISTER_A);
1069	DUMP_REG(DC_COM_SCRATCH_REGISTER_B);
1070	DUMP_REG(DC_COM_GPIO_CTRL);
1071	DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER);
1072	DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED);
1073	DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
1074	DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
1075	DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
1076	DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY);
1077	DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
1078	DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
1079	DUMP_REG(DC_DISP_REF_TO_SYNC);
1080	DUMP_REG(DC_DISP_SYNC_WIDTH);
1081	DUMP_REG(DC_DISP_BACK_PORCH);
1082	DUMP_REG(DC_DISP_ACTIVE);
1083	DUMP_REG(DC_DISP_FRONT_PORCH);
1084	DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
1085	DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
1086	DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
1087	DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
1088	DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
1089	DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
1090	DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
1091	DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
1092	DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
1093	DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
1094	DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
1095	DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
1096	DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
1097	DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
1098	DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
1099	DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
1100	DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
1101	DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
1102	DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
1103	DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
1104	DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
1105	DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
1106	DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
1107	DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
1108	DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
1109	DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
1110	DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
1111	DUMP_REG(DC_DISP_M0_CONTROL);
1112	DUMP_REG(DC_DISP_M1_CONTROL);
1113	DUMP_REG(DC_DISP_DI_CONTROL);
1114	DUMP_REG(DC_DISP_PP_CONTROL);
1115	DUMP_REG(DC_DISP_PP_SELECT_A);
1116	DUMP_REG(DC_DISP_PP_SELECT_B);
1117	DUMP_REG(DC_DISP_PP_SELECT_C);
1118	DUMP_REG(DC_DISP_PP_SELECT_D);
1119	DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
1120	DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
1121	DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
1122	DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
1123	DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
1124	DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
1125	DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
1126	DUMP_REG(DC_DISP_BORDER_COLOR);
1127	DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
1128	DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
1129	DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
1130	DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
1131	DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
1132	DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
1133	DUMP_REG(DC_DISP_CURSOR_START_ADDR);
1134	DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
1135	DUMP_REG(DC_DISP_CURSOR_POSITION);
1136	DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
1137	DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
1138	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
1139	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
1140	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
1141	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
1142	DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
1143	DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
1144	DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
1145	DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST);
1146	DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
1147	DUMP_REG(DC_DISP_DAC_CRT_CTRL);
1148	DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
1149	DUMP_REG(DC_DISP_SD_CONTROL);
1150	DUMP_REG(DC_DISP_SD_CSC_COEFF);
1151	DUMP_REG(DC_DISP_SD_LUT(0));
1152	DUMP_REG(DC_DISP_SD_LUT(1));
1153	DUMP_REG(DC_DISP_SD_LUT(2));
1154	DUMP_REG(DC_DISP_SD_LUT(3));
1155	DUMP_REG(DC_DISP_SD_LUT(4));
1156	DUMP_REG(DC_DISP_SD_LUT(5));
1157	DUMP_REG(DC_DISP_SD_LUT(6));
1158	DUMP_REG(DC_DISP_SD_LUT(7));
1159	DUMP_REG(DC_DISP_SD_LUT(8));
1160	DUMP_REG(DC_DISP_SD_FLICKER_CONTROL);
1161	DUMP_REG(DC_DISP_DC_PIXEL_COUNT);
1162	DUMP_REG(DC_DISP_SD_HISTOGRAM(0));
1163	DUMP_REG(DC_DISP_SD_HISTOGRAM(1));
1164	DUMP_REG(DC_DISP_SD_HISTOGRAM(2));
1165	DUMP_REG(DC_DISP_SD_HISTOGRAM(3));
1166	DUMP_REG(DC_DISP_SD_HISTOGRAM(4));
1167	DUMP_REG(DC_DISP_SD_HISTOGRAM(5));
1168	DUMP_REG(DC_DISP_SD_HISTOGRAM(6));
1169	DUMP_REG(DC_DISP_SD_HISTOGRAM(7));
1170	DUMP_REG(DC_DISP_SD_BL_TF(0));
1171	DUMP_REG(DC_DISP_SD_BL_TF(1));
1172	DUMP_REG(DC_DISP_SD_BL_TF(2));
1173	DUMP_REG(DC_DISP_SD_BL_TF(3));
1174	DUMP_REG(DC_DISP_SD_BL_CONTROL);
1175	DUMP_REG(DC_DISP_SD_HW_K_VALUES);
1176	DUMP_REG(DC_DISP_SD_MAN_K_VALUES);
1177	DUMP_REG(DC_DISP_CURSOR_START_ADDR_HI);
1178	DUMP_REG(DC_DISP_BLEND_CURSOR_CONTROL);
1179	DUMP_REG(DC_WIN_WIN_OPTIONS);
1180	DUMP_REG(DC_WIN_BYTE_SWAP);
1181	DUMP_REG(DC_WIN_BUFFER_CONTROL);
1182	DUMP_REG(DC_WIN_COLOR_DEPTH);
1183	DUMP_REG(DC_WIN_POSITION);
1184	DUMP_REG(DC_WIN_SIZE);
1185	DUMP_REG(DC_WIN_PRESCALED_SIZE);
1186	DUMP_REG(DC_WIN_H_INITIAL_DDA);
1187	DUMP_REG(DC_WIN_V_INITIAL_DDA);
1188	DUMP_REG(DC_WIN_DDA_INC);
1189	DUMP_REG(DC_WIN_LINE_STRIDE);
1190	DUMP_REG(DC_WIN_BUF_STRIDE);
1191	DUMP_REG(DC_WIN_UV_BUF_STRIDE);
1192	DUMP_REG(DC_WIN_BUFFER_ADDR_MODE);
1193	DUMP_REG(DC_WIN_DV_CONTROL);
1194	DUMP_REG(DC_WIN_BLEND_NOKEY);
1195	DUMP_REG(DC_WIN_BLEND_1WIN);
1196	DUMP_REG(DC_WIN_BLEND_2WIN_X);
1197	DUMP_REG(DC_WIN_BLEND_2WIN_Y);
1198	DUMP_REG(DC_WIN_BLEND_3WIN_XY);
1199	DUMP_REG(DC_WIN_HP_FETCH_CONTROL);
1200	DUMP_REG(DC_WINBUF_START_ADDR);
1201	DUMP_REG(DC_WINBUF_START_ADDR_NS);
1202	DUMP_REG(DC_WINBUF_START_ADDR_U);
1203	DUMP_REG(DC_WINBUF_START_ADDR_U_NS);
1204	DUMP_REG(DC_WINBUF_START_ADDR_V);
1205	DUMP_REG(DC_WINBUF_START_ADDR_V_NS);
1206	DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
1207	DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS);
1208	DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
1209	DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS);
1210	DUMP_REG(DC_WINBUF_UFLOW_STATUS);
1211	DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS);
1212	DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS);
1213	DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS);
1214
1215#undef DUMP_REG
1216
1217	return 0;
1218}
1219
1220static struct drm_info_list debugfs_files[] = {
1221	{ "regs", tegra_dc_show_regs, 0, NULL },
1222};
1223
1224static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
1225{
1226	unsigned int i;
1227	char *name;
1228	int err;
1229
1230	name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
1231	dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
1232	kfree(name);
1233
1234	if (!dc->debugfs)
1235		return -ENOMEM;
1236
1237	dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1238				    GFP_KERNEL);
1239	if (!dc->debugfs_files) {
1240		err = -ENOMEM;
1241		goto remove;
1242	}
1243
1244	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1245		dc->debugfs_files[i].data = dc;
1246
1247	err = drm_debugfs_create_files(dc->debugfs_files,
1248				       ARRAY_SIZE(debugfs_files),
1249				       dc->debugfs, minor);
1250	if (err < 0)
1251		goto free;
1252
1253	dc->minor = minor;
1254
1255	return 0;
1256
1257free:
1258	kfree(dc->debugfs_files);
1259	dc->debugfs_files = NULL;
1260remove:
1261	debugfs_remove(dc->debugfs);
1262	dc->debugfs = NULL;
1263
1264	return err;
1265}
1266
1267static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
1268{
1269	drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
1270				 dc->minor);
1271	dc->minor = NULL;
1272
1273	kfree(dc->debugfs_files);
1274	dc->debugfs_files = NULL;
1275
1276	debugfs_remove(dc->debugfs);
1277	dc->debugfs = NULL;
1278
1279	return 0;
1280}
1281
1282static int tegra_dc_init(struct host1x_client *client)
1283{
1284	struct drm_device *drm = dev_get_drvdata(client->parent);
1285	struct tegra_dc *dc = host1x_client_to_dc(client);
1286	struct tegra_drm *tegra = drm->dev_private;
1287	int err;
1288
1289	drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
1290	drm_mode_crtc_set_gamma_size(&dc->base, 256);
1291	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1292
1293	/*
1294	 * Keep track of the minimum pitch alignment across all display
1295	 * controllers.
1296	 */
1297	if (dc->soc->pitch_align > tegra->pitch_align)
1298		tegra->pitch_align = dc->soc->pitch_align;
1299
1300	err = tegra_dc_rgb_init(drm, dc);
1301	if (err < 0 && err != -ENODEV) {
1302		dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
1303		return err;
1304	}
1305
1306	err = tegra_dc_add_planes(drm, dc);
1307	if (err < 0)
1308		return err;
1309
1310	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1311		err = tegra_dc_debugfs_init(dc, drm->primary);
1312		if (err < 0)
1313			dev_err(dc->dev, "debugfs setup failed: %d\n", err);
1314	}
1315
1316	err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
1317			       dev_name(dc->dev), dc);
1318	if (err < 0) {
1319		dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
1320			err);
1321		return err;
1322	}
1323
1324	return 0;
1325}
1326
1327static int tegra_dc_exit(struct host1x_client *client)
1328{
1329	struct tegra_dc *dc = host1x_client_to_dc(client);
1330	int err;
1331
1332	devm_free_irq(dc->dev, dc->irq, dc);
1333
1334	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1335		err = tegra_dc_debugfs_exit(dc);
1336		if (err < 0)
1337			dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
1338	}
1339
1340	err = tegra_dc_rgb_exit(dc);
1341	if (err) {
1342		dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
1343		return err;
1344	}
1345
1346	return 0;
1347}
1348
1349static const struct host1x_client_ops dc_client_ops = {
1350	.init = tegra_dc_init,
1351	.exit = tegra_dc_exit,
1352};
1353
1354static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
1355	.supports_interlacing = false,
1356	.supports_cursor = false,
1357	.supports_block_linear = false,
1358	.pitch_align = 8,
1359};
1360
1361static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
1362	.supports_interlacing = false,
1363	.supports_cursor = false,
1364	.supports_block_linear = false,
1365	.pitch_align = 8,
1366};
1367
1368static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
1369	.supports_interlacing = false,
1370	.supports_cursor = false,
1371	.supports_block_linear = false,
1372	.pitch_align = 64,
1373};
1374
1375static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
1376	.supports_interlacing = true,
1377	.supports_cursor = true,
1378	.supports_block_linear = true,
1379	.pitch_align = 64,
1380};
1381
1382static const struct of_device_id tegra_dc_of_match[] = {
1383	{
1384		.compatible = "nvidia,tegra124-dc",
1385		.data = &tegra124_dc_soc_info,
1386	}, {
1387		.compatible = "nvidia,tegra30-dc",
1388		.data = &tegra30_dc_soc_info,
1389	}, {
1390		.compatible = "nvidia,tegra20-dc",
1391		.data = &tegra20_dc_soc_info,
1392	}, {
1393		/* sentinel */
1394	}
1395};
1396MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
1397
1398static int tegra_dc_parse_dt(struct tegra_dc *dc)
1399{
1400	struct device_node *np;
1401	u32 value = 0;
1402	int err;
1403
1404	err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);
1405	if (err < 0) {
1406		dev_err(dc->dev, "missing \"nvidia,head\" property\n");
1407
1408		/*
1409		 * If the nvidia,head property isn't present, try to find the
1410		 * correct head number by looking up the position of this
1411		 * display controller's node within the device tree. Assuming
1412		 * that the nodes are ordered properly in the DTS file and
1413		 * that the translation into a flattened device tree blob
1414		 * preserves that ordering this will actually yield the right
1415		 * head number.
1416		 *
1417		 * If those assumptions don't hold, this will still work for
1418		 * cases where only a single display controller is used.
1419		 */
1420		for_each_matching_node(np, tegra_dc_of_match) {
1421			if (np == dc->dev->of_node)
1422				break;
1423
1424			value++;
1425		}
1426	}
1427
1428	dc->pipe = value;
1429
1430	return 0;
1431}
1432
1433static int tegra_dc_probe(struct platform_device *pdev)
1434{
1435	const struct of_device_id *id;
1436	struct resource *regs;
1437	struct tegra_dc *dc;
1438	int err;
1439
1440	dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
1441	if (!dc)
1442		return -ENOMEM;
1443
1444	id = of_match_node(tegra_dc_of_match, pdev->dev.of_node);
1445	if (!id)
1446		return -ENODEV;
1447
1448	spin_lock_init(&dc->lock);
1449	INIT_LIST_HEAD(&dc->list);
1450	dc->dev = &pdev->dev;
1451	dc->soc = id->data;
1452
1453	err = tegra_dc_parse_dt(dc);
1454	if (err < 0)
1455		return err;
1456
1457	dc->clk = devm_clk_get(&pdev->dev, NULL);
1458	if (IS_ERR(dc->clk)) {
1459		dev_err(&pdev->dev, "failed to get clock\n");
1460		return PTR_ERR(dc->clk);
1461	}
1462
1463	dc->rst = devm_reset_control_get(&pdev->dev, "dc");
1464	if (IS_ERR(dc->rst)) {
1465		dev_err(&pdev->dev, "failed to get reset\n");
1466		return PTR_ERR(dc->rst);
1467	}
1468
1469	err = clk_prepare_enable(dc->clk);
1470	if (err < 0)
1471		return err;
1472
1473	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1474	dc->regs = devm_ioremap_resource(&pdev->dev, regs);
1475	if (IS_ERR(dc->regs))
1476		return PTR_ERR(dc->regs);
1477
1478	dc->irq = platform_get_irq(pdev, 0);
1479	if (dc->irq < 0) {
1480		dev_err(&pdev->dev, "failed to get IRQ\n");
1481		return -ENXIO;
1482	}
1483
1484	INIT_LIST_HEAD(&dc->client.list);
1485	dc->client.ops = &dc_client_ops;
1486	dc->client.dev = &pdev->dev;
1487
1488	err = tegra_dc_rgb_probe(dc);
1489	if (err < 0 && err != -ENODEV) {
1490		dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
1491		return err;
1492	}
1493
1494	err = host1x_client_register(&dc->client);
1495	if (err < 0) {
1496		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1497			err);
1498		return err;
1499	}
1500
1501	platform_set_drvdata(pdev, dc);
1502
1503	return 0;
1504}
1505
1506static int tegra_dc_remove(struct platform_device *pdev)
1507{
1508	struct tegra_dc *dc = platform_get_drvdata(pdev);
1509	int err;
1510
1511	err = host1x_client_unregister(&dc->client);
1512	if (err < 0) {
1513		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1514			err);
1515		return err;
1516	}
1517
1518	err = tegra_dc_rgb_remove(dc);
1519	if (err < 0) {
1520		dev_err(&pdev->dev, "failed to remove RGB output: %d\n", err);
1521		return err;
1522	}
1523
1524	reset_control_assert(dc->rst);
1525	clk_disable_unprepare(dc->clk);
1526
1527	return 0;
1528}
1529
1530struct platform_driver tegra_dc_driver = {
1531	.driver = {
1532		.name = "tegra-dc",
1533		.owner = THIS_MODULE,
1534		.of_match_table = tegra_dc_of_match,
1535	},
1536	.probe = tegra_dc_probe,
1537	.remove = tegra_dc_remove,
1538};
1539