blob: 3aa0da6244db9c9cd3ea67c5a6bbb8f5b66e94f9 [file] [log] [blame]
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001/*
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>
Thierry Reding9eb9b222013-09-24 16:32:47 +020011#include <linux/debugfs.h>
Thierry Redingdf06b752014-06-26 21:41:53 +020012#include <linux/iommu.h>
Thierry Redingb9ff7ae2017-08-21 16:35:17 +020013#include <linux/of_device.h>
Thierry Reding33a8eb82015-08-03 13:20:49 +020014#include <linux/pm_runtime.h>
Stephen Warrenca480802013-11-06 16:20:54 -070015#include <linux/reset.h>
Thierry Redingd8f4a9e2012-11-15 21:28:22 +000016
Thierry Reding9c012702014-07-07 15:32:53 +020017#include <soc/tegra/pmc.h>
18
Arto Merilainende2ba662013-03-22 16:34:08 +020019#include "dc.h"
20#include "drm.h"
21#include "gem.h"
Thierry Reding5acd3512017-11-10 15:27:25 +010022#include "plane.h"
Thierry Redingd8f4a9e2012-11-15 21:28:22 +000023
Thierry Reding9d441892014-11-24 17:02:53 +010024#include <drm/drm_atomic.h>
Thierry Reding4aa3df72014-11-24 16:27:13 +010025#include <drm/drm_atomic_helper.h>
Daniel Vetter3cb9ae42014-10-29 10:03:57 +010026#include <drm/drm_plane_helper.h>
27
Thierry Reding791ddb12015-07-28 21:27:05 +020028static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)
29{
30 stats->frames = 0;
31 stats->vblank = 0;
32 stats->underflow = 0;
33 stats->overflow = 0;
34}
35
Thierry Redingd700ba72014-12-08 15:50:04 +010036/*
Thierry Reding86df2562014-12-08 16:03:53 +010037 * Reads the active copy of a register. This takes the dc->lock spinlock to
38 * prevent races with the VBLANK processing which also needs access to the
39 * active copy of some registers.
40 */
41static u32 tegra_dc_readl_active(struct tegra_dc *dc, unsigned long offset)
42{
43 unsigned long flags;
44 u32 value;
45
46 spin_lock_irqsave(&dc->lock, flags);
47
48 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
49 value = tegra_dc_readl(dc, offset);
50 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
51
52 spin_unlock_irqrestore(&dc->lock, flags);
53 return value;
54}
55
56/*
Thierry Redingd700ba72014-12-08 15:50:04 +010057 * Double-buffered registers have two copies: ASSEMBLY and ACTIVE. When the
58 * *_ACT_REQ bits are set the ASSEMBLY copy is latched into the ACTIVE copy.
59 * Latching happens mmediately if the display controller is in STOP mode or
60 * on the next frame boundary otherwise.
61 *
62 * Triple-buffered registers have three copies: ASSEMBLY, ARM and ACTIVE. The
63 * ASSEMBLY copy is latched into the ARM copy immediately after *_UPDATE bits
64 * are written. When the *_ACT_REQ bits are written, the ARM copy is latched
65 * into the ACTIVE copy, either immediately if the display controller is in
66 * STOP mode, or at the next frame boundary otherwise.
67 */
Thierry Reding62b9e062014-11-21 17:33:33 +010068void tegra_dc_commit(struct tegra_dc *dc)
Thierry Reding205d48e2014-10-21 13:41:46 +020069{
70 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
71 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
72}
73
Thierry Reding10288ee2014-03-14 09:54:58 +010074static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
75 unsigned int bpp)
76{
77 fixed20_12 outf = dfixed_init(out);
78 fixed20_12 inf = dfixed_init(in);
79 u32 dda_inc;
80 int max;
81
82 if (v)
83 max = 15;
84 else {
85 switch (bpp) {
86 case 2:
87 max = 8;
88 break;
89
90 default:
91 WARN_ON_ONCE(1);
92 /* fallthrough */
93 case 4:
94 max = 4;
95 break;
96 }
97 }
98
99 outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
100 inf.full -= dfixed_const(1);
101
102 dda_inc = dfixed_div(inf, outf);
103 dda_inc = min_t(u32, dda_inc, dfixed_const(max));
104
105 return dda_inc;
106}
107
108static inline u32 compute_initial_dda(unsigned int in)
109{
110 fixed20_12 inf = dfixed_init(in);
111 return dfixed_frac(inf);
112}
113
Thierry Reding4aa3df72014-11-24 16:27:13 +0100114static void tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
115 const struct tegra_dc_window *window)
Thierry Reding10288ee2014-03-14 09:54:58 +0100116{
117 unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
Sean Paul93396d02014-11-19 13:04:49 -0500118 unsigned long value, flags;
Thierry Reding10288ee2014-03-14 09:54:58 +0100119 bool yuv, planar;
120
121 /*
122 * For YUV planar modes, the number of bytes per pixel takes into
123 * account only the luma component and therefore is 1.
124 */
Thierry Reding5acd3512017-11-10 15:27:25 +0100125 yuv = tegra_plane_format_is_yuv(window->format, &planar);
Thierry Reding10288ee2014-03-14 09:54:58 +0100126 if (!yuv)
127 bpp = window->bits_per_pixel / 8;
128 else
129 bpp = planar ? 1 : 2;
130
Sean Paul93396d02014-11-19 13:04:49 -0500131 spin_lock_irqsave(&dc->lock, flags);
132
Thierry Reding10288ee2014-03-14 09:54:58 +0100133 value = WINDOW_A_SELECT << index;
134 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
135
136 tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
137 tegra_dc_writel(dc, window->swap, DC_WIN_BYTE_SWAP);
138
139 value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
140 tegra_dc_writel(dc, value, DC_WIN_POSITION);
141
142 value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
143 tegra_dc_writel(dc, value, DC_WIN_SIZE);
144
145 h_offset = window->src.x * bpp;
146 v_offset = window->src.y;
147 h_size = window->src.w * bpp;
148 v_size = window->src.h;
149
150 value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
151 tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
152
153 /*
154 * For DDA computations the number of bytes per pixel for YUV planar
155 * modes needs to take into account all Y, U and V components.
156 */
157 if (yuv && planar)
158 bpp = 2;
159
160 h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
161 v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
162
163 value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
164 tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
165
166 h_dda = compute_initial_dda(window->src.x);
167 v_dda = compute_initial_dda(window->src.y);
168
169 tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
170 tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
171
172 tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
173 tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
174
175 tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
176
177 if (yuv && planar) {
178 tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
179 tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
180 value = window->stride[1] << 16 | window->stride[0];
181 tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
182 } else {
183 tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
184 }
185
186 if (window->bottom_up)
187 v_offset += window->src.h - 1;
188
189 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
190 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
191
Thierry Redingc134f012014-06-03 14:48:12 +0200192 if (dc->soc->supports_block_linear) {
193 unsigned long height = window->tiling.value;
Thierry Reding10288ee2014-03-14 09:54:58 +0100194
Thierry Redingc134f012014-06-03 14:48:12 +0200195 switch (window->tiling.mode) {
196 case TEGRA_BO_TILING_MODE_PITCH:
197 value = DC_WINBUF_SURFACE_KIND_PITCH;
198 break;
199
200 case TEGRA_BO_TILING_MODE_TILED:
201 value = DC_WINBUF_SURFACE_KIND_TILED;
202 break;
203
204 case TEGRA_BO_TILING_MODE_BLOCK:
205 value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
206 DC_WINBUF_SURFACE_KIND_BLOCK;
207 break;
208 }
209
210 tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
211 } else {
212 switch (window->tiling.mode) {
213 case TEGRA_BO_TILING_MODE_PITCH:
214 value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
215 DC_WIN_BUFFER_ADDR_MODE_LINEAR;
216 break;
217
218 case TEGRA_BO_TILING_MODE_TILED:
219 value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
220 DC_WIN_BUFFER_ADDR_MODE_TILE;
221 break;
222
223 case TEGRA_BO_TILING_MODE_BLOCK:
Thierry Reding4aa3df72014-11-24 16:27:13 +0100224 /*
225 * No need to handle this here because ->atomic_check
226 * will already have filtered it out.
227 */
228 break;
Thierry Redingc134f012014-06-03 14:48:12 +0200229 }
230
231 tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
232 }
Thierry Reding10288ee2014-03-14 09:54:58 +0100233
234 value = WIN_ENABLE;
235
236 if (yuv) {
237 /* setup default colorspace conversion coefficients */
238 tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
239 tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
240 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
241 tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
242 tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
243 tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
244 tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
245 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
246
247 value |= CSC_ENABLE;
248 } else if (window->bits_per_pixel < 24) {
249 value |= COLOR_EXPAND;
250 }
251
252 if (window->bottom_up)
253 value |= V_DIRECTION;
254
255 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
256
257 /*
258 * Disable blending and assume Window A is the bottom-most window,
259 * Window C is the top-most window and Window B is in the middle.
260 */
261 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
262 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
263
264 switch (index) {
265 case 0:
266 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
267 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
268 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
269 break;
270
271 case 1:
272 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
273 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
274 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
275 break;
276
277 case 2:
278 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
279 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
280 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
281 break;
282 }
283
Sean Paul93396d02014-11-19 13:04:49 -0500284 spin_unlock_irqrestore(&dc->lock, flags);
Thierry Redingc7679302014-10-21 13:51:53 +0200285}
286
Thierry Redingc7679302014-10-21 13:51:53 +0200287static const u32 tegra_primary_plane_formats[] = {
288 DRM_FORMAT_XBGR8888,
289 DRM_FORMAT_XRGB8888,
290 DRM_FORMAT_RGB565,
291};
292
Thierry Reding4aa3df72014-11-24 16:27:13 +0100293static int tegra_plane_atomic_check(struct drm_plane *plane,
294 struct drm_plane_state *state)
295{
Thierry Reding8f604f82014-11-28 13:14:55 +0100296 struct tegra_plane_state *plane_state = to_tegra_plane_state(state);
297 struct tegra_bo_tiling *tiling = &plane_state->tiling;
Thierry Reding47802b02014-11-26 12:28:39 +0100298 struct tegra_plane *tegra = to_tegra_plane(plane);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100299 struct tegra_dc *dc = to_tegra_dc(state->crtc);
Thierry Redingc7679302014-10-21 13:51:53 +0200300 int err;
301
Thierry Reding4aa3df72014-11-24 16:27:13 +0100302 /* no need for further checks if the plane is being disabled */
303 if (!state->crtc)
304 return 0;
305
Thierry Reding5acd3512017-11-10 15:27:25 +0100306 err = tegra_plane_format(state->fb->format->format,
307 &plane_state->format,
308 &plane_state->swap);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100309 if (err < 0)
310 return err;
311
Thierry Reding8f604f82014-11-28 13:14:55 +0100312 err = tegra_fb_get_tiling(state->fb, tiling);
313 if (err < 0)
314 return err;
315
316 if (tiling->mode == TEGRA_BO_TILING_MODE_BLOCK &&
Thierry Reding4aa3df72014-11-24 16:27:13 +0100317 !dc->soc->supports_block_linear) {
318 DRM_ERROR("hardware doesn't support block linear mode\n");
319 return -EINVAL;
320 }
321
322 /*
323 * Tegra doesn't support different strides for U and V planes so we
324 * error out if the user tries to display a framebuffer with such a
325 * configuration.
326 */
Ville Syrjäläbcb0b462016-12-14 23:30:22 +0200327 if (state->fb->format->num_planes > 2) {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100328 if (state->fb->pitches[2] != state->fb->pitches[1]) {
329 DRM_ERROR("unsupported UV-plane configuration\n");
330 return -EINVAL;
331 }
332 }
333
Thierry Reding47802b02014-11-26 12:28:39 +0100334 err = tegra_plane_state_add(tegra, state);
335 if (err < 0)
336 return err;
337
Thierry Reding4aa3df72014-11-24 16:27:13 +0100338 return 0;
339}
340
Thierry Redinga4bfa092017-08-30 17:34:10 +0200341static void tegra_plane_atomic_disable(struct drm_plane *plane,
342 struct drm_plane_state *old_state)
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300343{
Thierry Redinga4bfa092017-08-30 17:34:10 +0200344 struct tegra_dc *dc = to_tegra_dc(old_state->crtc);
345 struct tegra_plane *p = to_tegra_plane(plane);
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300346 unsigned long flags;
347 u32 value;
348
Thierry Redinga4bfa092017-08-30 17:34:10 +0200349 /* rien ne va plus */
350 if (!old_state || !old_state->crtc)
351 return;
352
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300353 spin_lock_irqsave(&dc->lock, flags);
354
Thierry Redinga4bfa092017-08-30 17:34:10 +0200355 value = WINDOW_A_SELECT << p->index;
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300356 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
357
358 value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
359 value &= ~WIN_ENABLE;
360 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
361
362 spin_unlock_irqrestore(&dc->lock, flags);
363}
364
Thierry Reding4aa3df72014-11-24 16:27:13 +0100365static void tegra_plane_atomic_update(struct drm_plane *plane,
366 struct drm_plane_state *old_state)
367{
Thierry Reding8f604f82014-11-28 13:14:55 +0100368 struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100369 struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
370 struct drm_framebuffer *fb = plane->state->fb;
371 struct tegra_plane *p = to_tegra_plane(plane);
372 struct tegra_dc_window window;
373 unsigned int i;
Thierry Reding4aa3df72014-11-24 16:27:13 +0100374
375 /* rien ne va plus */
376 if (!plane->state->crtc || !plane->state->fb)
377 return;
378
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300379 if (!plane->state->visible)
Thierry Redinga4bfa092017-08-30 17:34:10 +0200380 return tegra_plane_atomic_disable(plane, old_state);
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300381
Thierry Redingc7679302014-10-21 13:51:53 +0200382 memset(&window, 0, sizeof(window));
Dmitry Osipenko7d205852017-06-15 02:18:30 +0300383 window.src.x = plane->state->src.x1 >> 16;
384 window.src.y = plane->state->src.y1 >> 16;
385 window.src.w = drm_rect_width(&plane->state->src) >> 16;
386 window.src.h = drm_rect_height(&plane->state->src) >> 16;
387 window.dst.x = plane->state->dst.x1;
388 window.dst.y = plane->state->dst.y1;
389 window.dst.w = drm_rect_width(&plane->state->dst);
390 window.dst.h = drm_rect_height(&plane->state->dst);
Ville Syrjälä272725c2016-12-14 23:32:20 +0200391 window.bits_per_pixel = fb->format->cpp[0] * 8;
Thierry Redingc7679302014-10-21 13:51:53 +0200392 window.bottom_up = tegra_fb_is_bottom_up(fb);
393
Thierry Reding8f604f82014-11-28 13:14:55 +0100394 /* copy from state */
395 window.tiling = state->tiling;
396 window.format = state->format;
397 window.swap = state->swap;
Thierry Redingc7679302014-10-21 13:51:53 +0200398
Ville Syrjäläbcb0b462016-12-14 23:30:22 +0200399 for (i = 0; i < fb->format->num_planes; i++) {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100400 struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
Thierry Redingc7679302014-10-21 13:51:53 +0200401
Thierry Reding4aa3df72014-11-24 16:27:13 +0100402 window.base[i] = bo->paddr + fb->offsets[i];
Dmitry Osipenko08ee0172016-08-21 11:57:58 +0300403
404 /*
405 * Tegra uses a shared stride for UV planes. Framebuffers are
406 * already checked for this in the tegra_plane_atomic_check()
407 * function, so it's safe to ignore the V-plane pitch here.
408 */
409 if (i < 2)
410 window.stride[i] = fb->pitches[i];
Thierry Reding4aa3df72014-11-24 16:27:13 +0100411 }
Thierry Redingc7679302014-10-21 13:51:53 +0200412
Thierry Reding4aa3df72014-11-24 16:27:13 +0100413 tegra_dc_setup_window(dc, p->index, &window);
Thierry Redingc7679302014-10-21 13:51:53 +0200414}
415
Thierry Redinga4bfa092017-08-30 17:34:10 +0200416static const struct drm_plane_helper_funcs tegra_plane_helper_funcs = {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100417 .atomic_check = tegra_plane_atomic_check,
Thierry Reding4aa3df72014-11-24 16:27:13 +0100418 .atomic_disable = tegra_plane_atomic_disable,
Thierry Redinga4bfa092017-08-30 17:34:10 +0200419 .atomic_update = tegra_plane_atomic_update,
Thierry Redingc7679302014-10-21 13:51:53 +0200420};
421
422static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm,
423 struct tegra_dc *dc)
424{
Thierry Reding518e6222014-12-16 18:04:08 +0100425 /*
426 * Ideally this would use drm_crtc_mask(), but that would require the
427 * CRTC to already be in the mode_config's list of CRTCs. However, it
428 * will only be added to that list in the drm_crtc_init_with_planes()
429 * (in tegra_dc_init()), which in turn requires registration of these
430 * planes. So we have ourselves a nice little chicken and egg problem
431 * here.
432 *
433 * We work around this by manually creating the mask from the number
434 * of CRTCs that have been registered, and should therefore always be
435 * the same as drm_crtc_index() after registration.
436 */
437 unsigned long possible_crtcs = 1 << drm->mode_config.num_crtc;
Thierry Redingc7679302014-10-21 13:51:53 +0200438 struct tegra_plane *plane;
439 unsigned int num_formats;
440 const u32 *formats;
441 int err;
442
443 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
444 if (!plane)
445 return ERR_PTR(-ENOMEM);
446
447 num_formats = ARRAY_SIZE(tegra_primary_plane_formats);
448 formats = tegra_primary_plane_formats;
449
Thierry Reding518e6222014-12-16 18:04:08 +0100450 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
Thierry Redingc1cb4b62017-08-30 18:04:12 +0200451 &tegra_plane_funcs, formats,
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700452 num_formats, NULL,
453 DRM_PLANE_TYPE_PRIMARY, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200454 if (err < 0) {
455 kfree(plane);
456 return ERR_PTR(err);
457 }
458
Thierry Redinga4bfa092017-08-30 17:34:10 +0200459 drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100460
Thierry Redingc7679302014-10-21 13:51:53 +0200461 return &plane->base;
462}
463
464static const u32 tegra_cursor_plane_formats[] = {
465 DRM_FORMAT_RGBA8888,
466};
467
Thierry Reding4aa3df72014-11-24 16:27:13 +0100468static int tegra_cursor_atomic_check(struct drm_plane *plane,
469 struct drm_plane_state *state)
Thierry Redingc7679302014-10-21 13:51:53 +0200470{
Thierry Reding47802b02014-11-26 12:28:39 +0100471 struct tegra_plane *tegra = to_tegra_plane(plane);
472 int err;
473
Thierry Reding4aa3df72014-11-24 16:27:13 +0100474 /* no need for further checks if the plane is being disabled */
475 if (!state->crtc)
476 return 0;
Thierry Redingc7679302014-10-21 13:51:53 +0200477
478 /* scaling not supported for cursor */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100479 if ((state->src_w >> 16 != state->crtc_w) ||
480 (state->src_h >> 16 != state->crtc_h))
Thierry Redingc7679302014-10-21 13:51:53 +0200481 return -EINVAL;
482
483 /* only square cursors supported */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100484 if (state->src_w != state->src_h)
Thierry Redingc7679302014-10-21 13:51:53 +0200485 return -EINVAL;
486
Thierry Reding4aa3df72014-11-24 16:27:13 +0100487 if (state->crtc_w != 32 && state->crtc_w != 64 &&
488 state->crtc_w != 128 && state->crtc_w != 256)
489 return -EINVAL;
490
Thierry Reding47802b02014-11-26 12:28:39 +0100491 err = tegra_plane_state_add(tegra, state);
492 if (err < 0)
493 return err;
494
Thierry Reding4aa3df72014-11-24 16:27:13 +0100495 return 0;
496}
497
498static void tegra_cursor_atomic_update(struct drm_plane *plane,
499 struct drm_plane_state *old_state)
500{
501 struct tegra_bo *bo = tegra_fb_get_plane(plane->state->fb, 0);
502 struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
503 struct drm_plane_state *state = plane->state;
504 u32 value = CURSOR_CLIP_DISPLAY;
505
506 /* rien ne va plus */
507 if (!plane->state->crtc || !plane->state->fb)
508 return;
509
510 switch (state->crtc_w) {
Thierry Redingc7679302014-10-21 13:51:53 +0200511 case 32:
512 value |= CURSOR_SIZE_32x32;
513 break;
514
515 case 64:
516 value |= CURSOR_SIZE_64x64;
517 break;
518
519 case 128:
520 value |= CURSOR_SIZE_128x128;
521 break;
522
523 case 256:
524 value |= CURSOR_SIZE_256x256;
525 break;
526
527 default:
Thierry Reding4aa3df72014-11-24 16:27:13 +0100528 WARN(1, "cursor size %ux%u not supported\n", state->crtc_w,
529 state->crtc_h);
530 return;
Thierry Redingc7679302014-10-21 13:51:53 +0200531 }
532
533 value |= (bo->paddr >> 10) & 0x3fffff;
534 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
535
536#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
537 value = (bo->paddr >> 32) & 0x3;
538 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
539#endif
540
541 /* enable cursor and set blend mode */
542 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
543 value |= CURSOR_ENABLE;
544 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
545
546 value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
547 value &= ~CURSOR_DST_BLEND_MASK;
548 value &= ~CURSOR_SRC_BLEND_MASK;
549 value |= CURSOR_MODE_NORMAL;
550 value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC;
551 value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
552 value |= CURSOR_ALPHA;
553 tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
554
555 /* position the cursor */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100556 value = (state->crtc_y & 0x3fff) << 16 | (state->crtc_x & 0x3fff);
Thierry Redingc7679302014-10-21 13:51:53 +0200557 tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
Thierry Redingc7679302014-10-21 13:51:53 +0200558}
559
Thierry Reding4aa3df72014-11-24 16:27:13 +0100560static void tegra_cursor_atomic_disable(struct drm_plane *plane,
561 struct drm_plane_state *old_state)
Thierry Redingc7679302014-10-21 13:51:53 +0200562{
Thierry Reding4aa3df72014-11-24 16:27:13 +0100563 struct tegra_dc *dc;
Thierry Redingc7679302014-10-21 13:51:53 +0200564 u32 value;
565
Thierry Reding4aa3df72014-11-24 16:27:13 +0100566 /* rien ne va plus */
567 if (!old_state || !old_state->crtc)
568 return;
569
570 dc = to_tegra_dc(old_state->crtc);
Thierry Redingc7679302014-10-21 13:51:53 +0200571
572 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
573 value &= ~CURSOR_ENABLE;
574 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc7679302014-10-21 13:51:53 +0200575}
576
Thierry Reding4aa3df72014-11-24 16:27:13 +0100577static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100578 .atomic_check = tegra_cursor_atomic_check,
579 .atomic_update = tegra_cursor_atomic_update,
580 .atomic_disable = tegra_cursor_atomic_disable,
Thierry Redingc7679302014-10-21 13:51:53 +0200581};
582
583static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
584 struct tegra_dc *dc)
585{
586 struct tegra_plane *plane;
587 unsigned int num_formats;
588 const u32 *formats;
589 int err;
590
591 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
592 if (!plane)
593 return ERR_PTR(-ENOMEM);
594
Thierry Reding47802b02014-11-26 12:28:39 +0100595 /*
Thierry Redinga1df3b22015-07-21 16:42:30 +0200596 * This index is kind of fake. The cursor isn't a regular plane, but
597 * its update and activation request bits in DC_CMD_STATE_CONTROL do
598 * use the same programming. Setting this fake index here allows the
599 * code in tegra_add_plane_state() to do the right thing without the
600 * need to special-casing the cursor plane.
Thierry Reding47802b02014-11-26 12:28:39 +0100601 */
602 plane->index = 6;
603
Thierry Redingc7679302014-10-21 13:51:53 +0200604 num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
605 formats = tegra_cursor_plane_formats;
606
607 err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
Thierry Redingc1cb4b62017-08-30 18:04:12 +0200608 &tegra_plane_funcs, formats,
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700609 num_formats, NULL,
610 DRM_PLANE_TYPE_CURSOR, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200611 if (err < 0) {
612 kfree(plane);
613 return ERR_PTR(err);
614 }
615
Thierry Reding4aa3df72014-11-24 16:27:13 +0100616 drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs);
617
Thierry Redingc7679302014-10-21 13:51:53 +0200618 return &plane->base;
619}
620
Thierry Redingc7679302014-10-21 13:51:53 +0200621static const uint32_t tegra_overlay_plane_formats[] = {
Thierry Redingdbe4d9a2013-03-22 15:37:30 +0100622 DRM_FORMAT_XBGR8888,
Thierry Redingf34bc782012-11-04 21:47:13 +0100623 DRM_FORMAT_XRGB8888,
Thierry Redingdbe4d9a2013-03-22 15:37:30 +0100624 DRM_FORMAT_RGB565,
Thierry Redingf34bc782012-11-04 21:47:13 +0100625 DRM_FORMAT_UYVY,
Thierry Redingf9253902014-01-29 20:31:17 +0100626 DRM_FORMAT_YUYV,
Thierry Redingf34bc782012-11-04 21:47:13 +0100627 DRM_FORMAT_YUV420,
628 DRM_FORMAT_YUV422,
629};
630
Thierry Redingc7679302014-10-21 13:51:53 +0200631static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
632 struct tegra_dc *dc,
633 unsigned int index)
634{
635 struct tegra_plane *plane;
636 unsigned int num_formats;
637 const u32 *formats;
638 int err;
639
640 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
641 if (!plane)
642 return ERR_PTR(-ENOMEM);
643
644 plane->index = index;
645
646 num_formats = ARRAY_SIZE(tegra_overlay_plane_formats);
647 formats = tegra_overlay_plane_formats;
648
649 err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
Thierry Reding301e0dd2017-08-30 18:04:12 +0200650 &tegra_plane_funcs, formats,
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700651 num_formats, NULL,
652 DRM_PLANE_TYPE_OVERLAY, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200653 if (err < 0) {
654 kfree(plane);
655 return ERR_PTR(err);
656 }
657
Thierry Redinga4bfa092017-08-30 17:34:10 +0200658 drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100659
Thierry Redingc7679302014-10-21 13:51:53 +0200660 return &plane->base;
661}
662
Thierry Redingf34bc782012-11-04 21:47:13 +0100663static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
664{
Thierry Redingc7679302014-10-21 13:51:53 +0200665 struct drm_plane *plane;
Thierry Redingf34bc782012-11-04 21:47:13 +0100666 unsigned int i;
Thierry Redingf34bc782012-11-04 21:47:13 +0100667
668 for (i = 0; i < 2; i++) {
Thierry Redingc7679302014-10-21 13:51:53 +0200669 plane = tegra_dc_overlay_plane_create(drm, dc, 1 + i);
670 if (IS_ERR(plane))
671 return PTR_ERR(plane);
Thierry Redingf34bc782012-11-04 21:47:13 +0100672 }
673
674 return 0;
675}
676
Thierry Redingf002abc2013-10-14 14:06:02 +0200677static void tegra_dc_destroy(struct drm_crtc *crtc)
678{
679 drm_crtc_cleanup(crtc);
Thierry Redingf002abc2013-10-14 14:06:02 +0200680}
681
Thierry Redingca915b12014-12-08 16:14:45 +0100682static void tegra_crtc_reset(struct drm_crtc *crtc)
683{
684 struct tegra_dc_state *state;
685
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100686 if (crtc->state)
Daniel Vetterec2dc6a2016-05-09 16:34:09 +0200687 __drm_atomic_helper_crtc_destroy_state(crtc->state);
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100688
Thierry Redingca915b12014-12-08 16:14:45 +0100689 kfree(crtc->state);
690 crtc->state = NULL;
691
692 state = kzalloc(sizeof(*state), GFP_KERNEL);
Thierry Reding332bbe72015-01-28 15:03:31 +0100693 if (state) {
Thierry Redingca915b12014-12-08 16:14:45 +0100694 crtc->state = &state->base;
Thierry Reding332bbe72015-01-28 15:03:31 +0100695 crtc->state->crtc = crtc;
696 }
Thierry Reding31930d42015-07-02 17:04:06 +0200697
698 drm_crtc_vblank_reset(crtc);
Thierry Redingca915b12014-12-08 16:14:45 +0100699}
700
701static struct drm_crtc_state *
702tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
703{
704 struct tegra_dc_state *state = to_dc_state(crtc->state);
705 struct tegra_dc_state *copy;
706
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100707 copy = kmalloc(sizeof(*copy), GFP_KERNEL);
Thierry Redingca915b12014-12-08 16:14:45 +0100708 if (!copy)
709 return NULL;
710
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100711 __drm_atomic_helper_crtc_duplicate_state(crtc, &copy->base);
712 copy->clk = state->clk;
713 copy->pclk = state->pclk;
714 copy->div = state->div;
715 copy->planes = state->planes;
Thierry Redingca915b12014-12-08 16:14:45 +0100716
717 return &copy->base;
718}
719
720static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
721 struct drm_crtc_state *state)
722{
Daniel Vetterec2dc6a2016-05-09 16:34:09 +0200723 __drm_atomic_helper_crtc_destroy_state(state);
Thierry Redingca915b12014-12-08 16:14:45 +0100724 kfree(state);
725}
726
Thierry Redingb95800e2017-11-08 13:40:54 +0100727#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
728
729static const struct debugfs_reg32 tegra_dc_regs[] = {
730 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT),
731 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL),
732 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_ERROR),
733 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT),
734 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL),
735 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_ERROR),
736 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT),
737 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL),
738 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_ERROR),
739 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT),
740 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL),
741 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_ERROR),
742 DEBUGFS_REG32(DC_CMD_CONT_SYNCPT_VSYNC),
743 DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND_OPTION0),
744 DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND),
745 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE),
746 DEBUGFS_REG32(DC_CMD_DISPLAY_POWER_CONTROL),
747 DEBUGFS_REG32(DC_CMD_INT_STATUS),
748 DEBUGFS_REG32(DC_CMD_INT_MASK),
749 DEBUGFS_REG32(DC_CMD_INT_ENABLE),
750 DEBUGFS_REG32(DC_CMD_INT_TYPE),
751 DEBUGFS_REG32(DC_CMD_INT_POLARITY),
752 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE1),
753 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE2),
754 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE3),
755 DEBUGFS_REG32(DC_CMD_STATE_ACCESS),
756 DEBUGFS_REG32(DC_CMD_STATE_CONTROL),
757 DEBUGFS_REG32(DC_CMD_DISPLAY_WINDOW_HEADER),
758 DEBUGFS_REG32(DC_CMD_REG_ACT_CONTROL),
759 DEBUGFS_REG32(DC_COM_CRC_CONTROL),
760 DEBUGFS_REG32(DC_COM_CRC_CHECKSUM),
761 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(0)),
762 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(1)),
763 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(2)),
764 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(3)),
765 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(0)),
766 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(1)),
767 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(2)),
768 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(3)),
769 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(0)),
770 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(1)),
771 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(2)),
772 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(3)),
773 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(0)),
774 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(1)),
775 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(2)),
776 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(3)),
777 DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(0)),
778 DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(1)),
779 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(0)),
780 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(1)),
781 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(2)),
782 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(3)),
783 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(4)),
784 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(5)),
785 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(6)),
786 DEBUGFS_REG32(DC_COM_PIN_MISC_CONTROL),
787 DEBUGFS_REG32(DC_COM_PIN_PM0_CONTROL),
788 DEBUGFS_REG32(DC_COM_PIN_PM0_DUTY_CYCLE),
789 DEBUGFS_REG32(DC_COM_PIN_PM1_CONTROL),
790 DEBUGFS_REG32(DC_COM_PIN_PM1_DUTY_CYCLE),
791 DEBUGFS_REG32(DC_COM_SPI_CONTROL),
792 DEBUGFS_REG32(DC_COM_SPI_START_BYTE),
793 DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_AB),
794 DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_CD),
795 DEBUGFS_REG32(DC_COM_HSPI_CS_DC),
796 DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_A),
797 DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_B),
798 DEBUGFS_REG32(DC_COM_GPIO_CTRL),
799 DEBUGFS_REG32(DC_COM_GPIO_DEBOUNCE_COUNTER),
800 DEBUGFS_REG32(DC_COM_CRC_CHECKSUM_LATCHED),
801 DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS0),
802 DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS1),
803 DEBUGFS_REG32(DC_DISP_DISP_WIN_OPTIONS),
804 DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY),
805 DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER),
806 DEBUGFS_REG32(DC_DISP_DISP_TIMING_OPTIONS),
807 DEBUGFS_REG32(DC_DISP_REF_TO_SYNC),
808 DEBUGFS_REG32(DC_DISP_SYNC_WIDTH),
809 DEBUGFS_REG32(DC_DISP_BACK_PORCH),
810 DEBUGFS_REG32(DC_DISP_ACTIVE),
811 DEBUGFS_REG32(DC_DISP_FRONT_PORCH),
812 DEBUGFS_REG32(DC_DISP_H_PULSE0_CONTROL),
813 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_A),
814 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_B),
815 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_C),
816 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_D),
817 DEBUGFS_REG32(DC_DISP_H_PULSE1_CONTROL),
818 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_A),
819 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_B),
820 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_C),
821 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_D),
822 DEBUGFS_REG32(DC_DISP_H_PULSE2_CONTROL),
823 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_A),
824 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_B),
825 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_C),
826 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_D),
827 DEBUGFS_REG32(DC_DISP_V_PULSE0_CONTROL),
828 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_A),
829 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_B),
830 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_C),
831 DEBUGFS_REG32(DC_DISP_V_PULSE1_CONTROL),
832 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_A),
833 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_B),
834 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_C),
835 DEBUGFS_REG32(DC_DISP_V_PULSE2_CONTROL),
836 DEBUGFS_REG32(DC_DISP_V_PULSE2_POSITION_A),
837 DEBUGFS_REG32(DC_DISP_V_PULSE3_CONTROL),
838 DEBUGFS_REG32(DC_DISP_V_PULSE3_POSITION_A),
839 DEBUGFS_REG32(DC_DISP_M0_CONTROL),
840 DEBUGFS_REG32(DC_DISP_M1_CONTROL),
841 DEBUGFS_REG32(DC_DISP_DI_CONTROL),
842 DEBUGFS_REG32(DC_DISP_PP_CONTROL),
843 DEBUGFS_REG32(DC_DISP_PP_SELECT_A),
844 DEBUGFS_REG32(DC_DISP_PP_SELECT_B),
845 DEBUGFS_REG32(DC_DISP_PP_SELECT_C),
846 DEBUGFS_REG32(DC_DISP_PP_SELECT_D),
847 DEBUGFS_REG32(DC_DISP_DISP_CLOCK_CONTROL),
848 DEBUGFS_REG32(DC_DISP_DISP_INTERFACE_CONTROL),
849 DEBUGFS_REG32(DC_DISP_DISP_COLOR_CONTROL),
850 DEBUGFS_REG32(DC_DISP_SHIFT_CLOCK_OPTIONS),
851 DEBUGFS_REG32(DC_DISP_DATA_ENABLE_OPTIONS),
852 DEBUGFS_REG32(DC_DISP_SERIAL_INTERFACE_OPTIONS),
853 DEBUGFS_REG32(DC_DISP_LCD_SPI_OPTIONS),
854 DEBUGFS_REG32(DC_DISP_BORDER_COLOR),
855 DEBUGFS_REG32(DC_DISP_COLOR_KEY0_LOWER),
856 DEBUGFS_REG32(DC_DISP_COLOR_KEY0_UPPER),
857 DEBUGFS_REG32(DC_DISP_COLOR_KEY1_LOWER),
858 DEBUGFS_REG32(DC_DISP_COLOR_KEY1_UPPER),
859 DEBUGFS_REG32(DC_DISP_CURSOR_FOREGROUND),
860 DEBUGFS_REG32(DC_DISP_CURSOR_BACKGROUND),
861 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR),
862 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_NS),
863 DEBUGFS_REG32(DC_DISP_CURSOR_POSITION),
864 DEBUGFS_REG32(DC_DISP_CURSOR_POSITION_NS),
865 DEBUGFS_REG32(DC_DISP_INIT_SEQ_CONTROL),
866 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_A),
867 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_B),
868 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_C),
869 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_D),
870 DEBUGFS_REG32(DC_DISP_DC_MCCIF_FIFOCTRL),
871 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0A_HYST),
872 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0B_HYST),
873 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1A_HYST),
874 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1B_HYST),
875 DEBUGFS_REG32(DC_DISP_DAC_CRT_CTRL),
876 DEBUGFS_REG32(DC_DISP_DISP_MISC_CONTROL),
877 DEBUGFS_REG32(DC_DISP_SD_CONTROL),
878 DEBUGFS_REG32(DC_DISP_SD_CSC_COEFF),
879 DEBUGFS_REG32(DC_DISP_SD_LUT(0)),
880 DEBUGFS_REG32(DC_DISP_SD_LUT(1)),
881 DEBUGFS_REG32(DC_DISP_SD_LUT(2)),
882 DEBUGFS_REG32(DC_DISP_SD_LUT(3)),
883 DEBUGFS_REG32(DC_DISP_SD_LUT(4)),
884 DEBUGFS_REG32(DC_DISP_SD_LUT(5)),
885 DEBUGFS_REG32(DC_DISP_SD_LUT(6)),
886 DEBUGFS_REG32(DC_DISP_SD_LUT(7)),
887 DEBUGFS_REG32(DC_DISP_SD_LUT(8)),
888 DEBUGFS_REG32(DC_DISP_SD_FLICKER_CONTROL),
889 DEBUGFS_REG32(DC_DISP_DC_PIXEL_COUNT),
890 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(0)),
891 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(1)),
892 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(2)),
893 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(3)),
894 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(4)),
895 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(5)),
896 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(6)),
897 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(7)),
898 DEBUGFS_REG32(DC_DISP_SD_BL_TF(0)),
899 DEBUGFS_REG32(DC_DISP_SD_BL_TF(1)),
900 DEBUGFS_REG32(DC_DISP_SD_BL_TF(2)),
901 DEBUGFS_REG32(DC_DISP_SD_BL_TF(3)),
902 DEBUGFS_REG32(DC_DISP_SD_BL_CONTROL),
903 DEBUGFS_REG32(DC_DISP_SD_HW_K_VALUES),
904 DEBUGFS_REG32(DC_DISP_SD_MAN_K_VALUES),
905 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_HI),
906 DEBUGFS_REG32(DC_DISP_BLEND_CURSOR_CONTROL),
907 DEBUGFS_REG32(DC_WIN_WIN_OPTIONS),
908 DEBUGFS_REG32(DC_WIN_BYTE_SWAP),
909 DEBUGFS_REG32(DC_WIN_BUFFER_CONTROL),
910 DEBUGFS_REG32(DC_WIN_COLOR_DEPTH),
911 DEBUGFS_REG32(DC_WIN_POSITION),
912 DEBUGFS_REG32(DC_WIN_SIZE),
913 DEBUGFS_REG32(DC_WIN_PRESCALED_SIZE),
914 DEBUGFS_REG32(DC_WIN_H_INITIAL_DDA),
915 DEBUGFS_REG32(DC_WIN_V_INITIAL_DDA),
916 DEBUGFS_REG32(DC_WIN_DDA_INC),
917 DEBUGFS_REG32(DC_WIN_LINE_STRIDE),
918 DEBUGFS_REG32(DC_WIN_BUF_STRIDE),
919 DEBUGFS_REG32(DC_WIN_UV_BUF_STRIDE),
920 DEBUGFS_REG32(DC_WIN_BUFFER_ADDR_MODE),
921 DEBUGFS_REG32(DC_WIN_DV_CONTROL),
922 DEBUGFS_REG32(DC_WIN_BLEND_NOKEY),
923 DEBUGFS_REG32(DC_WIN_BLEND_1WIN),
924 DEBUGFS_REG32(DC_WIN_BLEND_2WIN_X),
925 DEBUGFS_REG32(DC_WIN_BLEND_2WIN_Y),
926 DEBUGFS_REG32(DC_WIN_BLEND_3WIN_XY),
927 DEBUGFS_REG32(DC_WIN_HP_FETCH_CONTROL),
928 DEBUGFS_REG32(DC_WINBUF_START_ADDR),
929 DEBUGFS_REG32(DC_WINBUF_START_ADDR_NS),
930 DEBUGFS_REG32(DC_WINBUF_START_ADDR_U),
931 DEBUGFS_REG32(DC_WINBUF_START_ADDR_U_NS),
932 DEBUGFS_REG32(DC_WINBUF_START_ADDR_V),
933 DEBUGFS_REG32(DC_WINBUF_START_ADDR_V_NS),
934 DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET),
935 DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET_NS),
936 DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET),
937 DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET_NS),
938 DEBUGFS_REG32(DC_WINBUF_UFLOW_STATUS),
939 DEBUGFS_REG32(DC_WINBUF_AD_UFLOW_STATUS),
940 DEBUGFS_REG32(DC_WINBUF_BD_UFLOW_STATUS),
941 DEBUGFS_REG32(DC_WINBUF_CD_UFLOW_STATUS),
942};
943
944static int tegra_dc_show_regs(struct seq_file *s, void *data)
945{
946 struct drm_info_node *node = s->private;
947 struct tegra_dc *dc = node->info_ent->data;
948 unsigned int i;
949 int err = 0;
950
951 drm_modeset_lock(&dc->base.mutex, NULL);
952
953 if (!dc->base.state->active) {
954 err = -EBUSY;
955 goto unlock;
956 }
957
958 for (i = 0; i < ARRAY_SIZE(tegra_dc_regs); i++) {
959 unsigned int offset = tegra_dc_regs[i].offset;
960
961 seq_printf(s, "%-40s %#05x %08x\n", tegra_dc_regs[i].name,
962 offset, tegra_dc_readl(dc, offset));
963 }
964
965unlock:
966 drm_modeset_unlock(&dc->base.mutex);
967 return err;
968}
969
970static int tegra_dc_show_crc(struct seq_file *s, void *data)
971{
972 struct drm_info_node *node = s->private;
973 struct tegra_dc *dc = node->info_ent->data;
974 int err = 0;
975 u32 value;
976
977 drm_modeset_lock(&dc->base.mutex, NULL);
978
979 if (!dc->base.state->active) {
980 err = -EBUSY;
981 goto unlock;
982 }
983
984 value = DC_COM_CRC_CONTROL_ACTIVE_DATA | DC_COM_CRC_CONTROL_ENABLE;
985 tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL);
986 tegra_dc_commit(dc);
987
988 drm_crtc_wait_one_vblank(&dc->base);
989 drm_crtc_wait_one_vblank(&dc->base);
990
991 value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM);
992 seq_printf(s, "%08x\n", value);
993
994 tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
995
996unlock:
997 drm_modeset_unlock(&dc->base.mutex);
998 return err;
999}
1000
1001static int tegra_dc_show_stats(struct seq_file *s, void *data)
1002{
1003 struct drm_info_node *node = s->private;
1004 struct tegra_dc *dc = node->info_ent->data;
1005
1006 seq_printf(s, "frames: %lu\n", dc->stats.frames);
1007 seq_printf(s, "vblank: %lu\n", dc->stats.vblank);
1008 seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
1009 seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
1010
1011 return 0;
1012}
1013
1014static struct drm_info_list debugfs_files[] = {
1015 { "regs", tegra_dc_show_regs, 0, NULL },
1016 { "crc", tegra_dc_show_crc, 0, NULL },
1017 { "stats", tegra_dc_show_stats, 0, NULL },
1018};
1019
1020static int tegra_dc_late_register(struct drm_crtc *crtc)
1021{
1022 unsigned int i, count = ARRAY_SIZE(debugfs_files);
1023 struct drm_minor *minor = crtc->dev->primary;
1024 struct dentry *root = crtc->debugfs_entry;
1025 struct tegra_dc *dc = to_tegra_dc(crtc);
1026 int err;
1027
1028 dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1029 GFP_KERNEL);
1030 if (!dc->debugfs_files)
1031 return -ENOMEM;
1032
1033 for (i = 0; i < count; i++)
1034 dc->debugfs_files[i].data = dc;
1035
1036 err = drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
1037 if (err < 0)
1038 goto free;
1039
1040 return 0;
1041
1042free:
1043 kfree(dc->debugfs_files);
1044 dc->debugfs_files = NULL;
1045
1046 return err;
1047}
1048
1049static void tegra_dc_early_unregister(struct drm_crtc *crtc)
1050{
1051 unsigned int count = ARRAY_SIZE(debugfs_files);
1052 struct drm_minor *minor = crtc->dev->primary;
1053 struct tegra_dc *dc = to_tegra_dc(crtc);
1054
1055 drm_debugfs_remove_files(dc->debugfs_files, count, minor);
1056 kfree(dc->debugfs_files);
1057 dc->debugfs_files = NULL;
1058}
1059
Thierry Redingc49c81e2017-11-08 13:32:05 +01001060static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc)
1061{
1062 struct tegra_dc *dc = to_tegra_dc(crtc);
1063
1064 if (dc->syncpt)
1065 return host1x_syncpt_read(dc->syncpt);
1066
1067 /* fallback to software emulated VBLANK counter */
1068 return drm_crtc_vblank_count(&dc->base);
1069}
1070
1071static int tegra_dc_enable_vblank(struct drm_crtc *crtc)
1072{
1073 struct tegra_dc *dc = to_tegra_dc(crtc);
1074 unsigned long value, flags;
1075
1076 spin_lock_irqsave(&dc->lock, flags);
1077
1078 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1079 value |= VBLANK_INT;
1080 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1081
1082 spin_unlock_irqrestore(&dc->lock, flags);
1083
1084 return 0;
1085}
1086
1087static void tegra_dc_disable_vblank(struct drm_crtc *crtc)
1088{
1089 struct tegra_dc *dc = to_tegra_dc(crtc);
1090 unsigned long value, flags;
1091
1092 spin_lock_irqsave(&dc->lock, flags);
1093
1094 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1095 value &= ~VBLANK_INT;
1096 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1097
1098 spin_unlock_irqrestore(&dc->lock, flags);
1099}
1100
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001101static const struct drm_crtc_funcs tegra_crtc_funcs = {
Thierry Reding1503ca42014-11-24 17:41:23 +01001102 .page_flip = drm_atomic_helper_page_flip,
Thierry Reding74f48792014-11-24 17:08:20 +01001103 .set_config = drm_atomic_helper_set_config,
Thierry Redingf002abc2013-10-14 14:06:02 +02001104 .destroy = tegra_dc_destroy,
Thierry Redingca915b12014-12-08 16:14:45 +01001105 .reset = tegra_crtc_reset,
1106 .atomic_duplicate_state = tegra_crtc_atomic_duplicate_state,
1107 .atomic_destroy_state = tegra_crtc_atomic_destroy_state,
Thierry Redingb95800e2017-11-08 13:40:54 +01001108 .late_register = tegra_dc_late_register,
1109 .early_unregister = tegra_dc_early_unregister,
Shawn Guo10437d92017-02-07 17:16:32 +08001110 .get_vblank_counter = tegra_dc_get_vblank_counter,
1111 .enable_vblank = tegra_dc_enable_vblank,
1112 .disable_vblank = tegra_dc_disable_vblank,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001113};
1114
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001115static int tegra_dc_set_timings(struct tegra_dc *dc,
1116 struct drm_display_mode *mode)
1117{
Thierry Reding0444c0f2014-04-16 09:22:38 +02001118 unsigned int h_ref_to_sync = 1;
1119 unsigned int v_ref_to_sync = 1;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001120 unsigned long value;
1121
1122 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
1123
1124 value = (v_ref_to_sync << 16) | h_ref_to_sync;
1125 tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
1126
1127 value = ((mode->vsync_end - mode->vsync_start) << 16) |
1128 ((mode->hsync_end - mode->hsync_start) << 0);
1129 tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
1130
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001131 value = ((mode->vtotal - mode->vsync_end) << 16) |
1132 ((mode->htotal - mode->hsync_end) << 0);
Lucas Stach40495082012-12-19 21:38:52 +00001133 tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
1134
1135 value = ((mode->vsync_start - mode->vdisplay) << 16) |
1136 ((mode->hsync_start - mode->hdisplay) << 0);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001137 tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
1138
1139 value = (mode->vdisplay << 16) | mode->hdisplay;
1140 tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
1141
1142 return 0;
1143}
1144
Thierry Reding9d910b62015-01-28 15:25:54 +01001145/**
1146 * tegra_dc_state_setup_clock - check clock settings and store them in atomic
1147 * state
1148 * @dc: display controller
1149 * @crtc_state: CRTC atomic state
1150 * @clk: parent clock for display controller
1151 * @pclk: pixel clock
1152 * @div: shift clock divider
1153 *
1154 * Returns:
1155 * 0 on success or a negative error-code on failure.
1156 */
Thierry Redingca915b12014-12-08 16:14:45 +01001157int tegra_dc_state_setup_clock(struct tegra_dc *dc,
1158 struct drm_crtc_state *crtc_state,
1159 struct clk *clk, unsigned long pclk,
1160 unsigned int div)
1161{
1162 struct tegra_dc_state *state = to_dc_state(crtc_state);
1163
Thierry Redingd2982742015-01-22 08:48:25 +01001164 if (!clk_has_parent(dc->clk, clk))
1165 return -EINVAL;
1166
Thierry Redingca915b12014-12-08 16:14:45 +01001167 state->clk = clk;
1168 state->pclk = pclk;
1169 state->div = div;
1170
1171 return 0;
1172}
1173
Thierry Reding76d59ed2014-12-19 15:09:16 +01001174static void tegra_dc_commit_state(struct tegra_dc *dc,
1175 struct tegra_dc_state *state)
1176{
1177 u32 value;
1178 int err;
1179
1180 err = clk_set_parent(dc->clk, state->clk);
1181 if (err < 0)
1182 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
1183
1184 /*
1185 * Outputs may not want to change the parent clock rate. This is only
1186 * relevant to Tegra20 where only a single display PLL is available.
1187 * Since that PLL would typically be used for HDMI, an internal LVDS
1188 * panel would need to be driven by some other clock such as PLL_P
1189 * which is shared with other peripherals. Changing the clock rate
1190 * should therefore be avoided.
1191 */
1192 if (state->pclk > 0) {
1193 err = clk_set_rate(state->clk, state->pclk);
1194 if (err < 0)
1195 dev_err(dc->dev,
1196 "failed to set clock rate to %lu Hz\n",
1197 state->pclk);
1198 }
1199
1200 DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),
1201 state->div);
1202 DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);
1203
1204 value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1;
1205 tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
Thierry Reding39e08af2017-08-30 17:38:39 +02001206
1207 err = clk_set_rate(dc->clk, state->pclk);
1208 if (err < 0)
1209 dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
1210 dc->clk, state->pclk, err);
Thierry Reding76d59ed2014-12-19 15:09:16 +01001211}
1212
Thierry Reding003fc842015-08-03 13:16:26 +02001213static void tegra_dc_stop(struct tegra_dc *dc)
1214{
1215 u32 value;
1216
1217 /* stop the display controller */
1218 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
1219 value &= ~DISP_CTRL_MODE_MASK;
1220 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
1221
1222 tegra_dc_commit(dc);
1223}
1224
1225static bool tegra_dc_idle(struct tegra_dc *dc)
1226{
1227 u32 value;
1228
1229 value = tegra_dc_readl_active(dc, DC_CMD_DISPLAY_COMMAND);
1230
1231 return (value & DISP_CTRL_MODE_MASK) == 0;
1232}
1233
1234static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout)
1235{
1236 timeout = jiffies + msecs_to_jiffies(timeout);
1237
1238 while (time_before(jiffies, timeout)) {
1239 if (tegra_dc_idle(dc))
1240 return 0;
1241
1242 usleep_range(1000, 2000);
1243 }
1244
1245 dev_dbg(dc->dev, "timeout waiting for DC to become idle\n");
1246 return -ETIMEDOUT;
1247}
1248
Laurent Pinchart64581712017-06-30 12:36:45 +03001249static void tegra_crtc_atomic_disable(struct drm_crtc *crtc,
1250 struct drm_crtc_state *old_state)
Thierry Reding003fc842015-08-03 13:16:26 +02001251{
1252 struct tegra_dc *dc = to_tegra_dc(crtc);
1253 u32 value;
1254
1255 if (!tegra_dc_idle(dc)) {
1256 tegra_dc_stop(dc);
1257
1258 /*
1259 * Ignore the return value, there isn't anything useful to do
1260 * in case this fails.
1261 */
1262 tegra_dc_wait_idle(dc, 100);
1263 }
1264
1265 /*
1266 * This should really be part of the RGB encoder driver, but clearing
1267 * these bits has the side-effect of stopping the display controller.
1268 * When that happens no VBLANK interrupts will be raised. At the same
1269 * time the encoder is disabled before the display controller, so the
1270 * above code is always going to timeout waiting for the controller
1271 * to go idle.
1272 *
1273 * Given the close coupling between the RGB encoder and the display
1274 * controller doing it here is still kind of okay. None of the other
1275 * encoder drivers require these bits to be cleared.
1276 *
1277 * XXX: Perhaps given that the display controller is switched off at
1278 * this point anyway maybe clearing these bits isn't even useful for
1279 * the RGB encoder?
1280 */
1281 if (dc->rgb) {
1282 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
1283 value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
1284 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
1285 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
1286 }
1287
1288 tegra_dc_stats_reset(&dc->stats);
1289 drm_crtc_vblank_off(crtc);
Thierry Reding33a8eb82015-08-03 13:20:49 +02001290
Thierry Reding9d99ab62017-10-12 17:40:46 +02001291 spin_lock_irq(&crtc->dev->event_lock);
1292
1293 if (crtc->state->event) {
1294 drm_crtc_send_vblank_event(crtc, crtc->state->event);
1295 crtc->state->event = NULL;
1296 }
1297
1298 spin_unlock_irq(&crtc->dev->event_lock);
1299
Thierry Reding33a8eb82015-08-03 13:20:49 +02001300 pm_runtime_put_sync(dc->dev);
Thierry Reding003fc842015-08-03 13:16:26 +02001301}
1302
Laurent Pinchart0b20a0f2017-06-30 12:36:44 +03001303static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
1304 struct drm_crtc_state *old_state)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001305{
Thierry Reding4aa3df72014-11-24 16:27:13 +01001306 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
Thierry Reding76d59ed2014-12-19 15:09:16 +01001307 struct tegra_dc_state *state = to_dc_state(crtc->state);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001308 struct tegra_dc *dc = to_tegra_dc(crtc);
Thierry Redingdbb3f2f2014-03-26 12:32:14 +01001309 u32 value;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001310
Thierry Reding33a8eb82015-08-03 13:20:49 +02001311 pm_runtime_get_sync(dc->dev);
1312
1313 /* initialize display controller */
1314 if (dc->syncpt) {
1315 u32 syncpt = host1x_syncpt_id(dc->syncpt);
1316
1317 value = SYNCPT_CNTRL_NO_STALL;
1318 tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
1319
1320 value = SYNCPT_VSYNC_ENABLE | syncpt;
1321 tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
1322 }
1323
1324 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1325 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1326 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
1327
1328 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1329 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1330 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
1331
1332 /* initialize timer */
1333 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
1334 WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
1335 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
1336
1337 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
1338 WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
1339 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
1340
1341 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1342 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1343 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
1344
1345 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1346 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1347 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1348
Thierry Reding7116e9a2017-11-13 11:20:48 +01001349 if (dc->soc->supports_background_color)
1350 tegra_dc_writel(dc, 0, DC_DISP_BLEND_BACKGROUND_COLOR);
1351 else
Thierry Reding33a8eb82015-08-03 13:20:49 +02001352 tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);
1353
1354 /* apply PLL and pixel clock changes */
Thierry Reding76d59ed2014-12-19 15:09:16 +01001355 tegra_dc_commit_state(dc, state);
1356
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001357 /* program display mode */
1358 tegra_dc_set_timings(dc, mode);
1359
Thierry Reding8620fc62013-12-12 11:03:59 +01001360 /* interlacing isn't supported yet, so disable it */
1361 if (dc->soc->supports_interlacing) {
1362 value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
1363 value &= ~INTERLACE_ENABLE;
1364 tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
1365 }
Thierry Reding666cb872014-12-08 16:32:47 +01001366
1367 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
1368 value &= ~DISP_CTRL_MODE_MASK;
1369 value |= DISP_CTRL_MODE_C_DISPLAY;
1370 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
1371
1372 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
1373 value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
1374 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
1375 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
1376
1377 tegra_dc_commit(dc);
Thierry Reding23fb4742012-11-28 11:38:24 +01001378
Thierry Reding8ff64c12014-10-08 14:48:51 +02001379 drm_crtc_vblank_on(crtc);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001380}
1381
Thierry Reding4aa3df72014-11-24 16:27:13 +01001382static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
1383 struct drm_crtc_state *state)
1384{
1385 return 0;
1386}
1387
Maarten Lankhorst613d2b22015-07-21 13:28:58 +02001388static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
1389 struct drm_crtc_state *old_crtc_state)
Thierry Reding4aa3df72014-11-24 16:27:13 +01001390{
Thierry Reding9d99ab62017-10-12 17:40:46 +02001391 unsigned long flags;
Thierry Reding1503ca42014-11-24 17:41:23 +01001392
1393 if (crtc->state->event) {
Thierry Reding9d99ab62017-10-12 17:40:46 +02001394 spin_lock_irqsave(&crtc->dev->event_lock, flags);
Thierry Reding1503ca42014-11-24 17:41:23 +01001395
Thierry Reding9d99ab62017-10-12 17:40:46 +02001396 if (drm_crtc_vblank_get(crtc) != 0)
1397 drm_crtc_send_vblank_event(crtc, crtc->state->event);
1398 else
1399 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
Thierry Reding1503ca42014-11-24 17:41:23 +01001400
Thierry Reding9d99ab62017-10-12 17:40:46 +02001401 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
1402
Thierry Reding1503ca42014-11-24 17:41:23 +01001403 crtc->state->event = NULL;
1404 }
Thierry Reding4aa3df72014-11-24 16:27:13 +01001405}
1406
Maarten Lankhorst613d2b22015-07-21 13:28:58 +02001407static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
1408 struct drm_crtc_state *old_crtc_state)
Thierry Reding4aa3df72014-11-24 16:27:13 +01001409{
Thierry Reding47802b02014-11-26 12:28:39 +01001410 struct tegra_dc_state *state = to_dc_state(crtc->state);
1411 struct tegra_dc *dc = to_tegra_dc(crtc);
1412
1413 tegra_dc_writel(dc, state->planes << 8, DC_CMD_STATE_CONTROL);
1414 tegra_dc_writel(dc, state->planes, DC_CMD_STATE_CONTROL);
Thierry Reding4aa3df72014-11-24 16:27:13 +01001415}
1416
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001417static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
Thierry Reding4aa3df72014-11-24 16:27:13 +01001418 .atomic_check = tegra_crtc_atomic_check,
1419 .atomic_begin = tegra_crtc_atomic_begin,
1420 .atomic_flush = tegra_crtc_atomic_flush,
Laurent Pinchart0b20a0f2017-06-30 12:36:44 +03001421 .atomic_enable = tegra_crtc_atomic_enable,
Laurent Pinchart64581712017-06-30 12:36:45 +03001422 .atomic_disable = tegra_crtc_atomic_disable,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001423};
1424
Thierry Reding6e5ff992012-11-28 11:45:47 +01001425static irqreturn_t tegra_dc_irq(int irq, void *data)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001426{
1427 struct tegra_dc *dc = data;
1428 unsigned long status;
1429
1430 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
1431 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
1432
1433 if (status & FRAME_END_INT) {
1434 /*
1435 dev_dbg(dc->dev, "%s(): frame end\n", __func__);
1436 */
Thierry Reding791ddb12015-07-28 21:27:05 +02001437 dc->stats.frames++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001438 }
1439
1440 if (status & VBLANK_INT) {
1441 /*
1442 dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
1443 */
Thierry Redinged7dae52014-12-16 16:03:13 +01001444 drm_crtc_handle_vblank(&dc->base);
Thierry Reding791ddb12015-07-28 21:27:05 +02001445 dc->stats.vblank++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001446 }
1447
1448 if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
1449 /*
1450 dev_dbg(dc->dev, "%s(): underflow\n", __func__);
1451 */
Thierry Reding791ddb12015-07-28 21:27:05 +02001452 dc->stats.underflow++;
1453 }
1454
1455 if (status & (WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT)) {
1456 /*
1457 dev_dbg(dc->dev, "%s(): overflow\n", __func__);
1458 */
1459 dc->stats.overflow++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001460 }
1461
1462 return IRQ_HANDLED;
1463}
1464
Thierry Reding53fa7f72013-09-24 15:35:40 +02001465static int tegra_dc_init(struct host1x_client *client)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001466{
Thierry Reding9910f5c2014-05-22 09:57:15 +02001467 struct drm_device *drm = dev_get_drvdata(client->parent);
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001468 unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
Thierry Reding776dc382013-10-14 14:43:22 +02001469 struct tegra_dc *dc = host1x_client_to_dc(client);
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001470 struct tegra_drm *tegra = drm->dev_private;
Thierry Redingc7679302014-10-21 13:51:53 +02001471 struct drm_plane *primary = NULL;
1472 struct drm_plane *cursor = NULL;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001473 int err;
1474
Thierry Reding617dd7c2017-08-30 12:48:31 +02001475 dc->syncpt = host1x_syncpt_request(client, flags);
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001476 if (!dc->syncpt)
1477 dev_warn(dc->dev, "failed to allocate syncpoint\n");
1478
Thierry Redingdf06b752014-06-26 21:41:53 +02001479 if (tegra->domain) {
1480 err = iommu_attach_device(tegra->domain, dc->dev);
1481 if (err < 0) {
1482 dev_err(dc->dev, "failed to attach to domain: %d\n",
1483 err);
1484 return err;
1485 }
1486
1487 dc->domain = tegra->domain;
1488 }
1489
Thierry Redingc7679302014-10-21 13:51:53 +02001490 primary = tegra_dc_primary_plane_create(drm, dc);
1491 if (IS_ERR(primary)) {
1492 err = PTR_ERR(primary);
1493 goto cleanup;
1494 }
1495
1496 if (dc->soc->supports_cursor) {
1497 cursor = tegra_dc_cursor_plane_create(drm, dc);
1498 if (IS_ERR(cursor)) {
1499 err = PTR_ERR(cursor);
1500 goto cleanup;
1501 }
1502 }
1503
1504 err = drm_crtc_init_with_planes(drm, &dc->base, primary, cursor,
Ville Syrjäläf9882872015-12-09 16:19:31 +02001505 &tegra_crtc_funcs, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +02001506 if (err < 0)
1507 goto cleanup;
1508
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001509 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1510
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001511 /*
1512 * Keep track of the minimum pitch alignment across all display
1513 * controllers.
1514 */
1515 if (dc->soc->pitch_align > tegra->pitch_align)
1516 tegra->pitch_align = dc->soc->pitch_align;
1517
Thierry Reding9910f5c2014-05-22 09:57:15 +02001518 err = tegra_dc_rgb_init(drm, dc);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001519 if (err < 0 && err != -ENODEV) {
1520 dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
Thierry Redingc7679302014-10-21 13:51:53 +02001521 goto cleanup;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001522 }
1523
Thierry Reding9910f5c2014-05-22 09:57:15 +02001524 err = tegra_dc_add_planes(drm, dc);
Thierry Redingf34bc782012-11-04 21:47:13 +01001525 if (err < 0)
Thierry Redingc7679302014-10-21 13:51:53 +02001526 goto cleanup;
Thierry Redingf34bc782012-11-04 21:47:13 +01001527
Thierry Reding6e5ff992012-11-28 11:45:47 +01001528 err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001529 dev_name(dc->dev), dc);
1530 if (err < 0) {
1531 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
1532 err);
Thierry Redingc7679302014-10-21 13:51:53 +02001533 goto cleanup;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001534 }
1535
1536 return 0;
Thierry Redingc7679302014-10-21 13:51:53 +02001537
1538cleanup:
1539 if (cursor)
1540 drm_plane_cleanup(cursor);
1541
1542 if (primary)
1543 drm_plane_cleanup(primary);
1544
1545 if (tegra->domain) {
1546 iommu_detach_device(tegra->domain, dc->dev);
1547 dc->domain = NULL;
1548 }
1549
1550 return err;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001551}
1552
Thierry Reding53fa7f72013-09-24 15:35:40 +02001553static int tegra_dc_exit(struct host1x_client *client)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001554{
Thierry Reding776dc382013-10-14 14:43:22 +02001555 struct tegra_dc *dc = host1x_client_to_dc(client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001556 int err;
1557
1558 devm_free_irq(dc->dev, dc->irq, dc);
1559
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001560 err = tegra_dc_rgb_exit(dc);
1561 if (err) {
1562 dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
1563 return err;
1564 }
1565
Thierry Redingdf06b752014-06-26 21:41:53 +02001566 if (dc->domain) {
1567 iommu_detach_device(dc->domain, dc->dev);
1568 dc->domain = NULL;
1569 }
1570
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001571 host1x_syncpt_free(dc->syncpt);
1572
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001573 return 0;
1574}
1575
1576static const struct host1x_client_ops dc_client_ops = {
Thierry Reding53fa7f72013-09-24 15:35:40 +02001577 .init = tegra_dc_init,
1578 .exit = tegra_dc_exit,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001579};
1580
Thierry Reding8620fc62013-12-12 11:03:59 +01001581static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001582 .supports_background_color = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001583 .supports_interlacing = false,
Thierry Redinge6876512013-12-20 13:58:33 +01001584 .supports_cursor = false,
Thierry Redingc134f012014-06-03 14:48:12 +02001585 .supports_block_linear = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001586 .pitch_align = 8,
Thierry Reding9c012702014-07-07 15:32:53 +02001587 .has_powergate = false,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001588 .broken_reset = true,
Thierry Reding8620fc62013-12-12 11:03:59 +01001589};
1590
1591static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001592 .supports_background_color = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001593 .supports_interlacing = false,
Thierry Redinge6876512013-12-20 13:58:33 +01001594 .supports_cursor = false,
Thierry Redingc134f012014-06-03 14:48:12 +02001595 .supports_block_linear = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001596 .pitch_align = 8,
Thierry Reding9c012702014-07-07 15:32:53 +02001597 .has_powergate = false,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001598 .broken_reset = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001599};
1600
1601static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001602 .supports_background_color = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001603 .supports_interlacing = false,
1604 .supports_cursor = false,
1605 .supports_block_linear = false,
1606 .pitch_align = 64,
Thierry Reding9c012702014-07-07 15:32:53 +02001607 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001608 .broken_reset = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001609};
1610
1611static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001612 .supports_background_color = true,
Thierry Reding8620fc62013-12-12 11:03:59 +01001613 .supports_interlacing = true,
Thierry Redinge6876512013-12-20 13:58:33 +01001614 .supports_cursor = true,
Thierry Redingc134f012014-06-03 14:48:12 +02001615 .supports_block_linear = true,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001616 .pitch_align = 64,
Thierry Reding9c012702014-07-07 15:32:53 +02001617 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001618 .broken_reset = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001619};
1620
Thierry Reding5b4f5162015-03-27 10:31:58 +01001621static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001622 .supports_background_color = true,
Thierry Reding5b4f5162015-03-27 10:31:58 +01001623 .supports_interlacing = true,
1624 .supports_cursor = true,
1625 .supports_block_linear = true,
1626 .pitch_align = 64,
1627 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001628 .broken_reset = false,
Thierry Reding5b4f5162015-03-27 10:31:58 +01001629};
1630
Thierry Reding8620fc62013-12-12 11:03:59 +01001631static const struct of_device_id tegra_dc_of_match[] = {
1632 {
Thierry Reding5b4f5162015-03-27 10:31:58 +01001633 .compatible = "nvidia,tegra210-dc",
1634 .data = &tegra210_dc_soc_info,
1635 }, {
Thierry Reding8620fc62013-12-12 11:03:59 +01001636 .compatible = "nvidia,tegra124-dc",
1637 .data = &tegra124_dc_soc_info,
1638 }, {
Thierry Reding9c012702014-07-07 15:32:53 +02001639 .compatible = "nvidia,tegra114-dc",
1640 .data = &tegra114_dc_soc_info,
1641 }, {
Thierry Reding8620fc62013-12-12 11:03:59 +01001642 .compatible = "nvidia,tegra30-dc",
1643 .data = &tegra30_dc_soc_info,
1644 }, {
1645 .compatible = "nvidia,tegra20-dc",
1646 .data = &tegra20_dc_soc_info,
1647 }, {
1648 /* sentinel */
1649 }
1650};
Stephen Warrenef707282014-06-18 16:21:55 -06001651MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
Thierry Reding8620fc62013-12-12 11:03:59 +01001652
Thierry Reding13411dd2014-01-09 17:08:36 +01001653static int tegra_dc_parse_dt(struct tegra_dc *dc)
1654{
1655 struct device_node *np;
1656 u32 value = 0;
1657 int err;
1658
1659 err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);
1660 if (err < 0) {
1661 dev_err(dc->dev, "missing \"nvidia,head\" property\n");
1662
1663 /*
1664 * If the nvidia,head property isn't present, try to find the
1665 * correct head number by looking up the position of this
1666 * display controller's node within the device tree. Assuming
1667 * that the nodes are ordered properly in the DTS file and
1668 * that the translation into a flattened device tree blob
1669 * preserves that ordering this will actually yield the right
1670 * head number.
1671 *
1672 * If those assumptions don't hold, this will still work for
1673 * cases where only a single display controller is used.
1674 */
1675 for_each_matching_node(np, tegra_dc_of_match) {
Julia Lawallcf6b1742015-10-24 16:42:31 +02001676 if (np == dc->dev->of_node) {
1677 of_node_put(np);
Thierry Reding13411dd2014-01-09 17:08:36 +01001678 break;
Julia Lawallcf6b1742015-10-24 16:42:31 +02001679 }
Thierry Reding13411dd2014-01-09 17:08:36 +01001680
1681 value++;
1682 }
1683 }
1684
1685 dc->pipe = value;
1686
1687 return 0;
1688}
1689
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001690static int tegra_dc_probe(struct platform_device *pdev)
1691{
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001692 struct resource *regs;
1693 struct tegra_dc *dc;
1694 int err;
1695
1696 dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
1697 if (!dc)
1698 return -ENOMEM;
1699
Thierry Redingb9ff7ae2017-08-21 16:35:17 +02001700 dc->soc = of_device_get_match_data(&pdev->dev);
Thierry Reding8620fc62013-12-12 11:03:59 +01001701
Thierry Reding6e5ff992012-11-28 11:45:47 +01001702 spin_lock_init(&dc->lock);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001703 INIT_LIST_HEAD(&dc->list);
1704 dc->dev = &pdev->dev;
1705
Thierry Reding13411dd2014-01-09 17:08:36 +01001706 err = tegra_dc_parse_dt(dc);
1707 if (err < 0)
1708 return err;
1709
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001710 dc->clk = devm_clk_get(&pdev->dev, NULL);
1711 if (IS_ERR(dc->clk)) {
1712 dev_err(&pdev->dev, "failed to get clock\n");
1713 return PTR_ERR(dc->clk);
1714 }
1715
Stephen Warrenca480802013-11-06 16:20:54 -07001716 dc->rst = devm_reset_control_get(&pdev->dev, "dc");
1717 if (IS_ERR(dc->rst)) {
1718 dev_err(&pdev->dev, "failed to get reset\n");
1719 return PTR_ERR(dc->rst);
1720 }
1721
Thierry Redinga2f2f742017-08-30 17:41:00 +02001722 /* assert reset and disable clock */
1723 if (!dc->soc->broken_reset) {
1724 err = clk_prepare_enable(dc->clk);
1725 if (err < 0)
1726 return err;
1727
1728 usleep_range(2000, 4000);
1729
1730 err = reset_control_assert(dc->rst);
1731 if (err < 0)
1732 return err;
1733
1734 usleep_range(2000, 4000);
1735
1736 clk_disable_unprepare(dc->clk);
1737 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02001738
Thierry Reding9c012702014-07-07 15:32:53 +02001739 if (dc->soc->has_powergate) {
1740 if (dc->pipe == 0)
1741 dc->powergate = TEGRA_POWERGATE_DIS;
1742 else
1743 dc->powergate = TEGRA_POWERGATE_DISB;
1744
Thierry Reding33a8eb82015-08-03 13:20:49 +02001745 tegra_powergate_power_off(dc->powergate);
Thierry Reding9c012702014-07-07 15:32:53 +02001746 }
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001747
1748 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Thierry Redingd4ed6022013-01-21 11:09:02 +01001749 dc->regs = devm_ioremap_resource(&pdev->dev, regs);
1750 if (IS_ERR(dc->regs))
1751 return PTR_ERR(dc->regs);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001752
1753 dc->irq = platform_get_irq(pdev, 0);
1754 if (dc->irq < 0) {
1755 dev_err(&pdev->dev, "failed to get IRQ\n");
1756 return -ENXIO;
1757 }
1758
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001759 err = tegra_dc_rgb_probe(dc);
1760 if (err < 0 && err != -ENODEV) {
1761 dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
1762 return err;
1763 }
1764
Thierry Reding33a8eb82015-08-03 13:20:49 +02001765 platform_set_drvdata(pdev, dc);
1766 pm_runtime_enable(&pdev->dev);
1767
1768 INIT_LIST_HEAD(&dc->client.list);
1769 dc->client.ops = &dc_client_ops;
1770 dc->client.dev = &pdev->dev;
1771
Thierry Reding776dc382013-10-14 14:43:22 +02001772 err = host1x_client_register(&dc->client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001773 if (err < 0) {
1774 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1775 err);
1776 return err;
1777 }
1778
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001779 return 0;
1780}
1781
1782static int tegra_dc_remove(struct platform_device *pdev)
1783{
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001784 struct tegra_dc *dc = platform_get_drvdata(pdev);
1785 int err;
1786
Thierry Reding776dc382013-10-14 14:43:22 +02001787 err = host1x_client_unregister(&dc->client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001788 if (err < 0) {
1789 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1790 err);
1791 return err;
1792 }
1793
Thierry Reding59d29c02013-10-14 14:26:42 +02001794 err = tegra_dc_rgb_remove(dc);
1795 if (err < 0) {
1796 dev_err(&pdev->dev, "failed to remove RGB output: %d\n", err);
1797 return err;
1798 }
1799
Thierry Reding33a8eb82015-08-03 13:20:49 +02001800 pm_runtime_disable(&pdev->dev);
1801
1802 return 0;
1803}
1804
1805#ifdef CONFIG_PM
1806static int tegra_dc_suspend(struct device *dev)
1807{
1808 struct tegra_dc *dc = dev_get_drvdata(dev);
1809 int err;
1810
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001811 if (!dc->soc->broken_reset) {
1812 err = reset_control_assert(dc->rst);
1813 if (err < 0) {
1814 dev_err(dev, "failed to assert reset: %d\n", err);
1815 return err;
1816 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02001817 }
Thierry Reding9c012702014-07-07 15:32:53 +02001818
1819 if (dc->soc->has_powergate)
1820 tegra_powergate_power_off(dc->powergate);
1821
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001822 clk_disable_unprepare(dc->clk);
1823
1824 return 0;
1825}
1826
Thierry Reding33a8eb82015-08-03 13:20:49 +02001827static int tegra_dc_resume(struct device *dev)
1828{
1829 struct tegra_dc *dc = dev_get_drvdata(dev);
1830 int err;
1831
1832 if (dc->soc->has_powergate) {
1833 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
1834 dc->rst);
1835 if (err < 0) {
1836 dev_err(dev, "failed to power partition: %d\n", err);
1837 return err;
1838 }
1839 } else {
1840 err = clk_prepare_enable(dc->clk);
1841 if (err < 0) {
1842 dev_err(dev, "failed to enable clock: %d\n", err);
1843 return err;
1844 }
1845
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001846 if (!dc->soc->broken_reset) {
1847 err = reset_control_deassert(dc->rst);
1848 if (err < 0) {
1849 dev_err(dev,
1850 "failed to deassert reset: %d\n", err);
1851 return err;
1852 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02001853 }
1854 }
1855
1856 return 0;
1857}
1858#endif
1859
1860static const struct dev_pm_ops tegra_dc_pm_ops = {
1861 SET_RUNTIME_PM_OPS(tegra_dc_suspend, tegra_dc_resume, NULL)
1862};
1863
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001864struct platform_driver tegra_dc_driver = {
1865 .driver = {
1866 .name = "tegra-dc",
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001867 .of_match_table = tegra_dc_of_match,
Thierry Reding33a8eb82015-08-03 13:20:49 +02001868 .pm = &tegra_dc_pm_ops,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001869 },
1870 .probe = tegra_dc_probe,
1871 .remove = tegra_dc_remove,
1872};