blob: 25e998f8f339b64de36527f39b1a0cfee7aeabcd [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 Redingc4755fb2017-11-13 11:08:13 +0100450 /*
451 * XXX compute offset so that we can directly access windows.
452 *
453 * Always use window A as primary window.
454 */
455 plane->offset = 0;
456 plane->index = 0;
457 plane->depth = 255;
458
Thierry Reding518e6222014-12-16 18:04:08 +0100459 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
Thierry Redingc1cb4b62017-08-30 18:04:12 +0200460 &tegra_plane_funcs, formats,
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700461 num_formats, NULL,
462 DRM_PLANE_TYPE_PRIMARY, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200463 if (err < 0) {
464 kfree(plane);
465 return ERR_PTR(err);
466 }
467
Thierry Redinga4bfa092017-08-30 17:34:10 +0200468 drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100469
Thierry Redingc7679302014-10-21 13:51:53 +0200470 return &plane->base;
471}
472
473static const u32 tegra_cursor_plane_formats[] = {
474 DRM_FORMAT_RGBA8888,
475};
476
Thierry Reding4aa3df72014-11-24 16:27:13 +0100477static int tegra_cursor_atomic_check(struct drm_plane *plane,
478 struct drm_plane_state *state)
Thierry Redingc7679302014-10-21 13:51:53 +0200479{
Thierry Reding47802b02014-11-26 12:28:39 +0100480 struct tegra_plane *tegra = to_tegra_plane(plane);
481 int err;
482
Thierry Reding4aa3df72014-11-24 16:27:13 +0100483 /* no need for further checks if the plane is being disabled */
484 if (!state->crtc)
485 return 0;
Thierry Redingc7679302014-10-21 13:51:53 +0200486
487 /* scaling not supported for cursor */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100488 if ((state->src_w >> 16 != state->crtc_w) ||
489 (state->src_h >> 16 != state->crtc_h))
Thierry Redingc7679302014-10-21 13:51:53 +0200490 return -EINVAL;
491
492 /* only square cursors supported */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100493 if (state->src_w != state->src_h)
Thierry Redingc7679302014-10-21 13:51:53 +0200494 return -EINVAL;
495
Thierry Reding4aa3df72014-11-24 16:27:13 +0100496 if (state->crtc_w != 32 && state->crtc_w != 64 &&
497 state->crtc_w != 128 && state->crtc_w != 256)
498 return -EINVAL;
499
Thierry Reding47802b02014-11-26 12:28:39 +0100500 err = tegra_plane_state_add(tegra, state);
501 if (err < 0)
502 return err;
503
Thierry Reding4aa3df72014-11-24 16:27:13 +0100504 return 0;
505}
506
507static void tegra_cursor_atomic_update(struct drm_plane *plane,
508 struct drm_plane_state *old_state)
509{
510 struct tegra_bo *bo = tegra_fb_get_plane(plane->state->fb, 0);
511 struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
512 struct drm_plane_state *state = plane->state;
513 u32 value = CURSOR_CLIP_DISPLAY;
514
515 /* rien ne va plus */
516 if (!plane->state->crtc || !plane->state->fb)
517 return;
518
519 switch (state->crtc_w) {
Thierry Redingc7679302014-10-21 13:51:53 +0200520 case 32:
521 value |= CURSOR_SIZE_32x32;
522 break;
523
524 case 64:
525 value |= CURSOR_SIZE_64x64;
526 break;
527
528 case 128:
529 value |= CURSOR_SIZE_128x128;
530 break;
531
532 case 256:
533 value |= CURSOR_SIZE_256x256;
534 break;
535
536 default:
Thierry Reding4aa3df72014-11-24 16:27:13 +0100537 WARN(1, "cursor size %ux%u not supported\n", state->crtc_w,
538 state->crtc_h);
539 return;
Thierry Redingc7679302014-10-21 13:51:53 +0200540 }
541
542 value |= (bo->paddr >> 10) & 0x3fffff;
543 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
544
545#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
546 value = (bo->paddr >> 32) & 0x3;
547 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
548#endif
549
550 /* enable cursor and set blend mode */
551 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
552 value |= CURSOR_ENABLE;
553 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
554
555 value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
556 value &= ~CURSOR_DST_BLEND_MASK;
557 value &= ~CURSOR_SRC_BLEND_MASK;
558 value |= CURSOR_MODE_NORMAL;
559 value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC;
560 value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
561 value |= CURSOR_ALPHA;
562 tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
563
564 /* position the cursor */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100565 value = (state->crtc_y & 0x3fff) << 16 | (state->crtc_x & 0x3fff);
Thierry Redingc7679302014-10-21 13:51:53 +0200566 tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
Thierry Redingc7679302014-10-21 13:51:53 +0200567}
568
Thierry Reding4aa3df72014-11-24 16:27:13 +0100569static void tegra_cursor_atomic_disable(struct drm_plane *plane,
570 struct drm_plane_state *old_state)
Thierry Redingc7679302014-10-21 13:51:53 +0200571{
Thierry Reding4aa3df72014-11-24 16:27:13 +0100572 struct tegra_dc *dc;
Thierry Redingc7679302014-10-21 13:51:53 +0200573 u32 value;
574
Thierry Reding4aa3df72014-11-24 16:27:13 +0100575 /* rien ne va plus */
576 if (!old_state || !old_state->crtc)
577 return;
578
579 dc = to_tegra_dc(old_state->crtc);
Thierry Redingc7679302014-10-21 13:51:53 +0200580
581 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
582 value &= ~CURSOR_ENABLE;
583 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc7679302014-10-21 13:51:53 +0200584}
585
Thierry Reding4aa3df72014-11-24 16:27:13 +0100586static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100587 .atomic_check = tegra_cursor_atomic_check,
588 .atomic_update = tegra_cursor_atomic_update,
589 .atomic_disable = tegra_cursor_atomic_disable,
Thierry Redingc7679302014-10-21 13:51:53 +0200590};
591
592static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
593 struct tegra_dc *dc)
594{
595 struct tegra_plane *plane;
596 unsigned int num_formats;
597 const u32 *formats;
598 int err;
599
600 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
601 if (!plane)
602 return ERR_PTR(-ENOMEM);
603
Thierry Reding47802b02014-11-26 12:28:39 +0100604 /*
Thierry Redinga1df3b22015-07-21 16:42:30 +0200605 * This index is kind of fake. The cursor isn't a regular plane, but
606 * its update and activation request bits in DC_CMD_STATE_CONTROL do
607 * use the same programming. Setting this fake index here allows the
608 * code in tegra_add_plane_state() to do the right thing without the
609 * need to special-casing the cursor plane.
Thierry Reding47802b02014-11-26 12:28:39 +0100610 */
611 plane->index = 6;
612
Thierry Redingc7679302014-10-21 13:51:53 +0200613 num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
614 formats = tegra_cursor_plane_formats;
615
616 err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
Thierry Redingc1cb4b62017-08-30 18:04:12 +0200617 &tegra_plane_funcs, formats,
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700618 num_formats, NULL,
619 DRM_PLANE_TYPE_CURSOR, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200620 if (err < 0) {
621 kfree(plane);
622 return ERR_PTR(err);
623 }
624
Thierry Reding4aa3df72014-11-24 16:27:13 +0100625 drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs);
626
Thierry Redingc7679302014-10-21 13:51:53 +0200627 return &plane->base;
628}
629
Thierry Redingc7679302014-10-21 13:51:53 +0200630static const uint32_t tegra_overlay_plane_formats[] = {
Thierry Redingdbe4d9a2013-03-22 15:37:30 +0100631 DRM_FORMAT_XBGR8888,
Thierry Redingf34bc782012-11-04 21:47:13 +0100632 DRM_FORMAT_XRGB8888,
Thierry Redingdbe4d9a2013-03-22 15:37:30 +0100633 DRM_FORMAT_RGB565,
Thierry Redingf34bc782012-11-04 21:47:13 +0100634 DRM_FORMAT_UYVY,
Thierry Redingf9253902014-01-29 20:31:17 +0100635 DRM_FORMAT_YUYV,
Thierry Redingf34bc782012-11-04 21:47:13 +0100636 DRM_FORMAT_YUV420,
637 DRM_FORMAT_YUV422,
638};
639
Thierry Redingc7679302014-10-21 13:51:53 +0200640static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
641 struct tegra_dc *dc,
642 unsigned int index)
643{
644 struct tegra_plane *plane;
645 unsigned int num_formats;
646 const u32 *formats;
647 int err;
648
649 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
650 if (!plane)
651 return ERR_PTR(-ENOMEM);
652
Thierry Redingc4755fb2017-11-13 11:08:13 +0100653 /* XXX compute offset so that we can directly access windows */
654 plane->offset = 0;
Thierry Redingc7679302014-10-21 13:51:53 +0200655 plane->index = index;
Thierry Redingc4755fb2017-11-13 11:08:13 +0100656 plane->depth = 0;
Thierry Redingc7679302014-10-21 13:51:53 +0200657
658 num_formats = ARRAY_SIZE(tegra_overlay_plane_formats);
659 formats = tegra_overlay_plane_formats;
660
661 err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
Thierry Reding301e0dd2017-08-30 18:04:12 +0200662 &tegra_plane_funcs, formats,
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700663 num_formats, NULL,
664 DRM_PLANE_TYPE_OVERLAY, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200665 if (err < 0) {
666 kfree(plane);
667 return ERR_PTR(err);
668 }
669
Thierry Redinga4bfa092017-08-30 17:34:10 +0200670 drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100671
Thierry Redingc7679302014-10-21 13:51:53 +0200672 return &plane->base;
673}
674
Thierry Redingf34bc782012-11-04 21:47:13 +0100675static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
676{
Thierry Redingc7679302014-10-21 13:51:53 +0200677 struct drm_plane *plane;
Thierry Redingf34bc782012-11-04 21:47:13 +0100678 unsigned int i;
Thierry Redingf34bc782012-11-04 21:47:13 +0100679
680 for (i = 0; i < 2; i++) {
Thierry Redingc7679302014-10-21 13:51:53 +0200681 plane = tegra_dc_overlay_plane_create(drm, dc, 1 + i);
682 if (IS_ERR(plane))
683 return PTR_ERR(plane);
Thierry Redingf34bc782012-11-04 21:47:13 +0100684 }
685
686 return 0;
687}
688
Thierry Redingf002abc2013-10-14 14:06:02 +0200689static void tegra_dc_destroy(struct drm_crtc *crtc)
690{
691 drm_crtc_cleanup(crtc);
Thierry Redingf002abc2013-10-14 14:06:02 +0200692}
693
Thierry Redingca915b12014-12-08 16:14:45 +0100694static void tegra_crtc_reset(struct drm_crtc *crtc)
695{
696 struct tegra_dc_state *state;
697
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100698 if (crtc->state)
Daniel Vetterec2dc6a2016-05-09 16:34:09 +0200699 __drm_atomic_helper_crtc_destroy_state(crtc->state);
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100700
Thierry Redingca915b12014-12-08 16:14:45 +0100701 kfree(crtc->state);
702 crtc->state = NULL;
703
704 state = kzalloc(sizeof(*state), GFP_KERNEL);
Thierry Reding332bbe72015-01-28 15:03:31 +0100705 if (state) {
Thierry Redingca915b12014-12-08 16:14:45 +0100706 crtc->state = &state->base;
Thierry Reding332bbe72015-01-28 15:03:31 +0100707 crtc->state->crtc = crtc;
708 }
Thierry Reding31930d42015-07-02 17:04:06 +0200709
710 drm_crtc_vblank_reset(crtc);
Thierry Redingca915b12014-12-08 16:14:45 +0100711}
712
713static struct drm_crtc_state *
714tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
715{
716 struct tegra_dc_state *state = to_dc_state(crtc->state);
717 struct tegra_dc_state *copy;
718
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100719 copy = kmalloc(sizeof(*copy), GFP_KERNEL);
Thierry Redingca915b12014-12-08 16:14:45 +0100720 if (!copy)
721 return NULL;
722
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100723 __drm_atomic_helper_crtc_duplicate_state(crtc, &copy->base);
724 copy->clk = state->clk;
725 copy->pclk = state->pclk;
726 copy->div = state->div;
727 copy->planes = state->planes;
Thierry Redingca915b12014-12-08 16:14:45 +0100728
729 return &copy->base;
730}
731
732static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
733 struct drm_crtc_state *state)
734{
Daniel Vetterec2dc6a2016-05-09 16:34:09 +0200735 __drm_atomic_helper_crtc_destroy_state(state);
Thierry Redingca915b12014-12-08 16:14:45 +0100736 kfree(state);
737}
738
Thierry Redingb95800e2017-11-08 13:40:54 +0100739#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
740
741static const struct debugfs_reg32 tegra_dc_regs[] = {
742 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT),
743 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL),
744 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_ERROR),
745 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT),
746 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL),
747 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_ERROR),
748 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT),
749 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL),
750 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_ERROR),
751 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT),
752 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL),
753 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_ERROR),
754 DEBUGFS_REG32(DC_CMD_CONT_SYNCPT_VSYNC),
755 DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND_OPTION0),
756 DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND),
757 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE),
758 DEBUGFS_REG32(DC_CMD_DISPLAY_POWER_CONTROL),
759 DEBUGFS_REG32(DC_CMD_INT_STATUS),
760 DEBUGFS_REG32(DC_CMD_INT_MASK),
761 DEBUGFS_REG32(DC_CMD_INT_ENABLE),
762 DEBUGFS_REG32(DC_CMD_INT_TYPE),
763 DEBUGFS_REG32(DC_CMD_INT_POLARITY),
764 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE1),
765 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE2),
766 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE3),
767 DEBUGFS_REG32(DC_CMD_STATE_ACCESS),
768 DEBUGFS_REG32(DC_CMD_STATE_CONTROL),
769 DEBUGFS_REG32(DC_CMD_DISPLAY_WINDOW_HEADER),
770 DEBUGFS_REG32(DC_CMD_REG_ACT_CONTROL),
771 DEBUGFS_REG32(DC_COM_CRC_CONTROL),
772 DEBUGFS_REG32(DC_COM_CRC_CHECKSUM),
773 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(0)),
774 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(1)),
775 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(2)),
776 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(3)),
777 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(0)),
778 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(1)),
779 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(2)),
780 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(3)),
781 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(0)),
782 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(1)),
783 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(2)),
784 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(3)),
785 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(0)),
786 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(1)),
787 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(2)),
788 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(3)),
789 DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(0)),
790 DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(1)),
791 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(0)),
792 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(1)),
793 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(2)),
794 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(3)),
795 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(4)),
796 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(5)),
797 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(6)),
798 DEBUGFS_REG32(DC_COM_PIN_MISC_CONTROL),
799 DEBUGFS_REG32(DC_COM_PIN_PM0_CONTROL),
800 DEBUGFS_REG32(DC_COM_PIN_PM0_DUTY_CYCLE),
801 DEBUGFS_REG32(DC_COM_PIN_PM1_CONTROL),
802 DEBUGFS_REG32(DC_COM_PIN_PM1_DUTY_CYCLE),
803 DEBUGFS_REG32(DC_COM_SPI_CONTROL),
804 DEBUGFS_REG32(DC_COM_SPI_START_BYTE),
805 DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_AB),
806 DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_CD),
807 DEBUGFS_REG32(DC_COM_HSPI_CS_DC),
808 DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_A),
809 DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_B),
810 DEBUGFS_REG32(DC_COM_GPIO_CTRL),
811 DEBUGFS_REG32(DC_COM_GPIO_DEBOUNCE_COUNTER),
812 DEBUGFS_REG32(DC_COM_CRC_CHECKSUM_LATCHED),
813 DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS0),
814 DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS1),
815 DEBUGFS_REG32(DC_DISP_DISP_WIN_OPTIONS),
816 DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY),
817 DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER),
818 DEBUGFS_REG32(DC_DISP_DISP_TIMING_OPTIONS),
819 DEBUGFS_REG32(DC_DISP_REF_TO_SYNC),
820 DEBUGFS_REG32(DC_DISP_SYNC_WIDTH),
821 DEBUGFS_REG32(DC_DISP_BACK_PORCH),
822 DEBUGFS_REG32(DC_DISP_ACTIVE),
823 DEBUGFS_REG32(DC_DISP_FRONT_PORCH),
824 DEBUGFS_REG32(DC_DISP_H_PULSE0_CONTROL),
825 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_A),
826 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_B),
827 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_C),
828 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_D),
829 DEBUGFS_REG32(DC_DISP_H_PULSE1_CONTROL),
830 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_A),
831 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_B),
832 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_C),
833 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_D),
834 DEBUGFS_REG32(DC_DISP_H_PULSE2_CONTROL),
835 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_A),
836 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_B),
837 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_C),
838 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_D),
839 DEBUGFS_REG32(DC_DISP_V_PULSE0_CONTROL),
840 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_A),
841 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_B),
842 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_C),
843 DEBUGFS_REG32(DC_DISP_V_PULSE1_CONTROL),
844 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_A),
845 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_B),
846 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_C),
847 DEBUGFS_REG32(DC_DISP_V_PULSE2_CONTROL),
848 DEBUGFS_REG32(DC_DISP_V_PULSE2_POSITION_A),
849 DEBUGFS_REG32(DC_DISP_V_PULSE3_CONTROL),
850 DEBUGFS_REG32(DC_DISP_V_PULSE3_POSITION_A),
851 DEBUGFS_REG32(DC_DISP_M0_CONTROL),
852 DEBUGFS_REG32(DC_DISP_M1_CONTROL),
853 DEBUGFS_REG32(DC_DISP_DI_CONTROL),
854 DEBUGFS_REG32(DC_DISP_PP_CONTROL),
855 DEBUGFS_REG32(DC_DISP_PP_SELECT_A),
856 DEBUGFS_REG32(DC_DISP_PP_SELECT_B),
857 DEBUGFS_REG32(DC_DISP_PP_SELECT_C),
858 DEBUGFS_REG32(DC_DISP_PP_SELECT_D),
859 DEBUGFS_REG32(DC_DISP_DISP_CLOCK_CONTROL),
860 DEBUGFS_REG32(DC_DISP_DISP_INTERFACE_CONTROL),
861 DEBUGFS_REG32(DC_DISP_DISP_COLOR_CONTROL),
862 DEBUGFS_REG32(DC_DISP_SHIFT_CLOCK_OPTIONS),
863 DEBUGFS_REG32(DC_DISP_DATA_ENABLE_OPTIONS),
864 DEBUGFS_REG32(DC_DISP_SERIAL_INTERFACE_OPTIONS),
865 DEBUGFS_REG32(DC_DISP_LCD_SPI_OPTIONS),
866 DEBUGFS_REG32(DC_DISP_BORDER_COLOR),
867 DEBUGFS_REG32(DC_DISP_COLOR_KEY0_LOWER),
868 DEBUGFS_REG32(DC_DISP_COLOR_KEY0_UPPER),
869 DEBUGFS_REG32(DC_DISP_COLOR_KEY1_LOWER),
870 DEBUGFS_REG32(DC_DISP_COLOR_KEY1_UPPER),
871 DEBUGFS_REG32(DC_DISP_CURSOR_FOREGROUND),
872 DEBUGFS_REG32(DC_DISP_CURSOR_BACKGROUND),
873 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR),
874 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_NS),
875 DEBUGFS_REG32(DC_DISP_CURSOR_POSITION),
876 DEBUGFS_REG32(DC_DISP_CURSOR_POSITION_NS),
877 DEBUGFS_REG32(DC_DISP_INIT_SEQ_CONTROL),
878 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_A),
879 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_B),
880 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_C),
881 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_D),
882 DEBUGFS_REG32(DC_DISP_DC_MCCIF_FIFOCTRL),
883 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0A_HYST),
884 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0B_HYST),
885 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1A_HYST),
886 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1B_HYST),
887 DEBUGFS_REG32(DC_DISP_DAC_CRT_CTRL),
888 DEBUGFS_REG32(DC_DISP_DISP_MISC_CONTROL),
889 DEBUGFS_REG32(DC_DISP_SD_CONTROL),
890 DEBUGFS_REG32(DC_DISP_SD_CSC_COEFF),
891 DEBUGFS_REG32(DC_DISP_SD_LUT(0)),
892 DEBUGFS_REG32(DC_DISP_SD_LUT(1)),
893 DEBUGFS_REG32(DC_DISP_SD_LUT(2)),
894 DEBUGFS_REG32(DC_DISP_SD_LUT(3)),
895 DEBUGFS_REG32(DC_DISP_SD_LUT(4)),
896 DEBUGFS_REG32(DC_DISP_SD_LUT(5)),
897 DEBUGFS_REG32(DC_DISP_SD_LUT(6)),
898 DEBUGFS_REG32(DC_DISP_SD_LUT(7)),
899 DEBUGFS_REG32(DC_DISP_SD_LUT(8)),
900 DEBUGFS_REG32(DC_DISP_SD_FLICKER_CONTROL),
901 DEBUGFS_REG32(DC_DISP_DC_PIXEL_COUNT),
902 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(0)),
903 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(1)),
904 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(2)),
905 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(3)),
906 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(4)),
907 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(5)),
908 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(6)),
909 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(7)),
910 DEBUGFS_REG32(DC_DISP_SD_BL_TF(0)),
911 DEBUGFS_REG32(DC_DISP_SD_BL_TF(1)),
912 DEBUGFS_REG32(DC_DISP_SD_BL_TF(2)),
913 DEBUGFS_REG32(DC_DISP_SD_BL_TF(3)),
914 DEBUGFS_REG32(DC_DISP_SD_BL_CONTROL),
915 DEBUGFS_REG32(DC_DISP_SD_HW_K_VALUES),
916 DEBUGFS_REG32(DC_DISP_SD_MAN_K_VALUES),
917 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_HI),
918 DEBUGFS_REG32(DC_DISP_BLEND_CURSOR_CONTROL),
919 DEBUGFS_REG32(DC_WIN_WIN_OPTIONS),
920 DEBUGFS_REG32(DC_WIN_BYTE_SWAP),
921 DEBUGFS_REG32(DC_WIN_BUFFER_CONTROL),
922 DEBUGFS_REG32(DC_WIN_COLOR_DEPTH),
923 DEBUGFS_REG32(DC_WIN_POSITION),
924 DEBUGFS_REG32(DC_WIN_SIZE),
925 DEBUGFS_REG32(DC_WIN_PRESCALED_SIZE),
926 DEBUGFS_REG32(DC_WIN_H_INITIAL_DDA),
927 DEBUGFS_REG32(DC_WIN_V_INITIAL_DDA),
928 DEBUGFS_REG32(DC_WIN_DDA_INC),
929 DEBUGFS_REG32(DC_WIN_LINE_STRIDE),
930 DEBUGFS_REG32(DC_WIN_BUF_STRIDE),
931 DEBUGFS_REG32(DC_WIN_UV_BUF_STRIDE),
932 DEBUGFS_REG32(DC_WIN_BUFFER_ADDR_MODE),
933 DEBUGFS_REG32(DC_WIN_DV_CONTROL),
934 DEBUGFS_REG32(DC_WIN_BLEND_NOKEY),
935 DEBUGFS_REG32(DC_WIN_BLEND_1WIN),
936 DEBUGFS_REG32(DC_WIN_BLEND_2WIN_X),
937 DEBUGFS_REG32(DC_WIN_BLEND_2WIN_Y),
938 DEBUGFS_REG32(DC_WIN_BLEND_3WIN_XY),
939 DEBUGFS_REG32(DC_WIN_HP_FETCH_CONTROL),
940 DEBUGFS_REG32(DC_WINBUF_START_ADDR),
941 DEBUGFS_REG32(DC_WINBUF_START_ADDR_NS),
942 DEBUGFS_REG32(DC_WINBUF_START_ADDR_U),
943 DEBUGFS_REG32(DC_WINBUF_START_ADDR_U_NS),
944 DEBUGFS_REG32(DC_WINBUF_START_ADDR_V),
945 DEBUGFS_REG32(DC_WINBUF_START_ADDR_V_NS),
946 DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET),
947 DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET_NS),
948 DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET),
949 DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET_NS),
950 DEBUGFS_REG32(DC_WINBUF_UFLOW_STATUS),
951 DEBUGFS_REG32(DC_WINBUF_AD_UFLOW_STATUS),
952 DEBUGFS_REG32(DC_WINBUF_BD_UFLOW_STATUS),
953 DEBUGFS_REG32(DC_WINBUF_CD_UFLOW_STATUS),
954};
955
956static int tegra_dc_show_regs(struct seq_file *s, void *data)
957{
958 struct drm_info_node *node = s->private;
959 struct tegra_dc *dc = node->info_ent->data;
960 unsigned int i;
961 int err = 0;
962
963 drm_modeset_lock(&dc->base.mutex, NULL);
964
965 if (!dc->base.state->active) {
966 err = -EBUSY;
967 goto unlock;
968 }
969
970 for (i = 0; i < ARRAY_SIZE(tegra_dc_regs); i++) {
971 unsigned int offset = tegra_dc_regs[i].offset;
972
973 seq_printf(s, "%-40s %#05x %08x\n", tegra_dc_regs[i].name,
974 offset, tegra_dc_readl(dc, offset));
975 }
976
977unlock:
978 drm_modeset_unlock(&dc->base.mutex);
979 return err;
980}
981
982static int tegra_dc_show_crc(struct seq_file *s, void *data)
983{
984 struct drm_info_node *node = s->private;
985 struct tegra_dc *dc = node->info_ent->data;
986 int err = 0;
987 u32 value;
988
989 drm_modeset_lock(&dc->base.mutex, NULL);
990
991 if (!dc->base.state->active) {
992 err = -EBUSY;
993 goto unlock;
994 }
995
996 value = DC_COM_CRC_CONTROL_ACTIVE_DATA | DC_COM_CRC_CONTROL_ENABLE;
997 tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL);
998 tegra_dc_commit(dc);
999
1000 drm_crtc_wait_one_vblank(&dc->base);
1001 drm_crtc_wait_one_vblank(&dc->base);
1002
1003 value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM);
1004 seq_printf(s, "%08x\n", value);
1005
1006 tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
1007
1008unlock:
1009 drm_modeset_unlock(&dc->base.mutex);
1010 return err;
1011}
1012
1013static int tegra_dc_show_stats(struct seq_file *s, void *data)
1014{
1015 struct drm_info_node *node = s->private;
1016 struct tegra_dc *dc = node->info_ent->data;
1017
1018 seq_printf(s, "frames: %lu\n", dc->stats.frames);
1019 seq_printf(s, "vblank: %lu\n", dc->stats.vblank);
1020 seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
1021 seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
1022
1023 return 0;
1024}
1025
1026static struct drm_info_list debugfs_files[] = {
1027 { "regs", tegra_dc_show_regs, 0, NULL },
1028 { "crc", tegra_dc_show_crc, 0, NULL },
1029 { "stats", tegra_dc_show_stats, 0, NULL },
1030};
1031
1032static int tegra_dc_late_register(struct drm_crtc *crtc)
1033{
1034 unsigned int i, count = ARRAY_SIZE(debugfs_files);
1035 struct drm_minor *minor = crtc->dev->primary;
1036 struct dentry *root = crtc->debugfs_entry;
1037 struct tegra_dc *dc = to_tegra_dc(crtc);
1038 int err;
1039
1040 dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1041 GFP_KERNEL);
1042 if (!dc->debugfs_files)
1043 return -ENOMEM;
1044
1045 for (i = 0; i < count; i++)
1046 dc->debugfs_files[i].data = dc;
1047
1048 err = drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
1049 if (err < 0)
1050 goto free;
1051
1052 return 0;
1053
1054free:
1055 kfree(dc->debugfs_files);
1056 dc->debugfs_files = NULL;
1057
1058 return err;
1059}
1060
1061static void tegra_dc_early_unregister(struct drm_crtc *crtc)
1062{
1063 unsigned int count = ARRAY_SIZE(debugfs_files);
1064 struct drm_minor *minor = crtc->dev->primary;
1065 struct tegra_dc *dc = to_tegra_dc(crtc);
1066
1067 drm_debugfs_remove_files(dc->debugfs_files, count, minor);
1068 kfree(dc->debugfs_files);
1069 dc->debugfs_files = NULL;
1070}
1071
Thierry Redingc49c81e2017-11-08 13:32:05 +01001072static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc)
1073{
1074 struct tegra_dc *dc = to_tegra_dc(crtc);
1075
1076 if (dc->syncpt)
1077 return host1x_syncpt_read(dc->syncpt);
1078
1079 /* fallback to software emulated VBLANK counter */
1080 return drm_crtc_vblank_count(&dc->base);
1081}
1082
1083static int tegra_dc_enable_vblank(struct drm_crtc *crtc)
1084{
1085 struct tegra_dc *dc = to_tegra_dc(crtc);
1086 unsigned long value, flags;
1087
1088 spin_lock_irqsave(&dc->lock, flags);
1089
1090 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1091 value |= VBLANK_INT;
1092 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1093
1094 spin_unlock_irqrestore(&dc->lock, flags);
1095
1096 return 0;
1097}
1098
1099static void tegra_dc_disable_vblank(struct drm_crtc *crtc)
1100{
1101 struct tegra_dc *dc = to_tegra_dc(crtc);
1102 unsigned long value, flags;
1103
1104 spin_lock_irqsave(&dc->lock, flags);
1105
1106 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1107 value &= ~VBLANK_INT;
1108 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1109
1110 spin_unlock_irqrestore(&dc->lock, flags);
1111}
1112
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001113static const struct drm_crtc_funcs tegra_crtc_funcs = {
Thierry Reding1503ca42014-11-24 17:41:23 +01001114 .page_flip = drm_atomic_helper_page_flip,
Thierry Reding74f48792014-11-24 17:08:20 +01001115 .set_config = drm_atomic_helper_set_config,
Thierry Redingf002abc2013-10-14 14:06:02 +02001116 .destroy = tegra_dc_destroy,
Thierry Redingca915b12014-12-08 16:14:45 +01001117 .reset = tegra_crtc_reset,
1118 .atomic_duplicate_state = tegra_crtc_atomic_duplicate_state,
1119 .atomic_destroy_state = tegra_crtc_atomic_destroy_state,
Thierry Redingb95800e2017-11-08 13:40:54 +01001120 .late_register = tegra_dc_late_register,
1121 .early_unregister = tegra_dc_early_unregister,
Shawn Guo10437d92017-02-07 17:16:32 +08001122 .get_vblank_counter = tegra_dc_get_vblank_counter,
1123 .enable_vblank = tegra_dc_enable_vblank,
1124 .disable_vblank = tegra_dc_disable_vblank,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001125};
1126
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001127static int tegra_dc_set_timings(struct tegra_dc *dc,
1128 struct drm_display_mode *mode)
1129{
Thierry Reding0444c0f2014-04-16 09:22:38 +02001130 unsigned int h_ref_to_sync = 1;
1131 unsigned int v_ref_to_sync = 1;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001132 unsigned long value;
1133
1134 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
1135
1136 value = (v_ref_to_sync << 16) | h_ref_to_sync;
1137 tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
1138
1139 value = ((mode->vsync_end - mode->vsync_start) << 16) |
1140 ((mode->hsync_end - mode->hsync_start) << 0);
1141 tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
1142
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001143 value = ((mode->vtotal - mode->vsync_end) << 16) |
1144 ((mode->htotal - mode->hsync_end) << 0);
Lucas Stach40495082012-12-19 21:38:52 +00001145 tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
1146
1147 value = ((mode->vsync_start - mode->vdisplay) << 16) |
1148 ((mode->hsync_start - mode->hdisplay) << 0);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001149 tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
1150
1151 value = (mode->vdisplay << 16) | mode->hdisplay;
1152 tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
1153
1154 return 0;
1155}
1156
Thierry Reding9d910b62015-01-28 15:25:54 +01001157/**
1158 * tegra_dc_state_setup_clock - check clock settings and store them in atomic
1159 * state
1160 * @dc: display controller
1161 * @crtc_state: CRTC atomic state
1162 * @clk: parent clock for display controller
1163 * @pclk: pixel clock
1164 * @div: shift clock divider
1165 *
1166 * Returns:
1167 * 0 on success or a negative error-code on failure.
1168 */
Thierry Redingca915b12014-12-08 16:14:45 +01001169int tegra_dc_state_setup_clock(struct tegra_dc *dc,
1170 struct drm_crtc_state *crtc_state,
1171 struct clk *clk, unsigned long pclk,
1172 unsigned int div)
1173{
1174 struct tegra_dc_state *state = to_dc_state(crtc_state);
1175
Thierry Redingd2982742015-01-22 08:48:25 +01001176 if (!clk_has_parent(dc->clk, clk))
1177 return -EINVAL;
1178
Thierry Redingca915b12014-12-08 16:14:45 +01001179 state->clk = clk;
1180 state->pclk = pclk;
1181 state->div = div;
1182
1183 return 0;
1184}
1185
Thierry Reding76d59ed2014-12-19 15:09:16 +01001186static void tegra_dc_commit_state(struct tegra_dc *dc,
1187 struct tegra_dc_state *state)
1188{
1189 u32 value;
1190 int err;
1191
1192 err = clk_set_parent(dc->clk, state->clk);
1193 if (err < 0)
1194 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
1195
1196 /*
1197 * Outputs may not want to change the parent clock rate. This is only
1198 * relevant to Tegra20 where only a single display PLL is available.
1199 * Since that PLL would typically be used for HDMI, an internal LVDS
1200 * panel would need to be driven by some other clock such as PLL_P
1201 * which is shared with other peripherals. Changing the clock rate
1202 * should therefore be avoided.
1203 */
1204 if (state->pclk > 0) {
1205 err = clk_set_rate(state->clk, state->pclk);
1206 if (err < 0)
1207 dev_err(dc->dev,
1208 "failed to set clock rate to %lu Hz\n",
1209 state->pclk);
1210 }
1211
1212 DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),
1213 state->div);
1214 DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);
1215
1216 value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1;
1217 tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
Thierry Reding39e08af2017-08-30 17:38:39 +02001218
1219 err = clk_set_rate(dc->clk, state->pclk);
1220 if (err < 0)
1221 dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
1222 dc->clk, state->pclk, err);
Thierry Reding76d59ed2014-12-19 15:09:16 +01001223}
1224
Thierry Reding003fc842015-08-03 13:16:26 +02001225static void tegra_dc_stop(struct tegra_dc *dc)
1226{
1227 u32 value;
1228
1229 /* stop the display controller */
1230 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
1231 value &= ~DISP_CTRL_MODE_MASK;
1232 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
1233
1234 tegra_dc_commit(dc);
1235}
1236
1237static bool tegra_dc_idle(struct tegra_dc *dc)
1238{
1239 u32 value;
1240
1241 value = tegra_dc_readl_active(dc, DC_CMD_DISPLAY_COMMAND);
1242
1243 return (value & DISP_CTRL_MODE_MASK) == 0;
1244}
1245
1246static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout)
1247{
1248 timeout = jiffies + msecs_to_jiffies(timeout);
1249
1250 while (time_before(jiffies, timeout)) {
1251 if (tegra_dc_idle(dc))
1252 return 0;
1253
1254 usleep_range(1000, 2000);
1255 }
1256
1257 dev_dbg(dc->dev, "timeout waiting for DC to become idle\n");
1258 return -ETIMEDOUT;
1259}
1260
Laurent Pinchart64581712017-06-30 12:36:45 +03001261static void tegra_crtc_atomic_disable(struct drm_crtc *crtc,
1262 struct drm_crtc_state *old_state)
Thierry Reding003fc842015-08-03 13:16:26 +02001263{
1264 struct tegra_dc *dc = to_tegra_dc(crtc);
1265 u32 value;
1266
1267 if (!tegra_dc_idle(dc)) {
1268 tegra_dc_stop(dc);
1269
1270 /*
1271 * Ignore the return value, there isn't anything useful to do
1272 * in case this fails.
1273 */
1274 tegra_dc_wait_idle(dc, 100);
1275 }
1276
1277 /*
1278 * This should really be part of the RGB encoder driver, but clearing
1279 * these bits has the side-effect of stopping the display controller.
1280 * When that happens no VBLANK interrupts will be raised. At the same
1281 * time the encoder is disabled before the display controller, so the
1282 * above code is always going to timeout waiting for the controller
1283 * to go idle.
1284 *
1285 * Given the close coupling between the RGB encoder and the display
1286 * controller doing it here is still kind of okay. None of the other
1287 * encoder drivers require these bits to be cleared.
1288 *
1289 * XXX: Perhaps given that the display controller is switched off at
1290 * this point anyway maybe clearing these bits isn't even useful for
1291 * the RGB encoder?
1292 */
1293 if (dc->rgb) {
1294 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
1295 value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
1296 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
1297 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
1298 }
1299
1300 tegra_dc_stats_reset(&dc->stats);
1301 drm_crtc_vblank_off(crtc);
Thierry Reding33a8eb82015-08-03 13:20:49 +02001302
Thierry Reding9d99ab62017-10-12 17:40:46 +02001303 spin_lock_irq(&crtc->dev->event_lock);
1304
1305 if (crtc->state->event) {
1306 drm_crtc_send_vblank_event(crtc, crtc->state->event);
1307 crtc->state->event = NULL;
1308 }
1309
1310 spin_unlock_irq(&crtc->dev->event_lock);
1311
Thierry Reding33a8eb82015-08-03 13:20:49 +02001312 pm_runtime_put_sync(dc->dev);
Thierry Reding003fc842015-08-03 13:16:26 +02001313}
1314
Laurent Pinchart0b20a0f2017-06-30 12:36:44 +03001315static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
1316 struct drm_crtc_state *old_state)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001317{
Thierry Reding4aa3df72014-11-24 16:27:13 +01001318 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
Thierry Reding76d59ed2014-12-19 15:09:16 +01001319 struct tegra_dc_state *state = to_dc_state(crtc->state);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001320 struct tegra_dc *dc = to_tegra_dc(crtc);
Thierry Redingdbb3f2f2014-03-26 12:32:14 +01001321 u32 value;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001322
Thierry Reding33a8eb82015-08-03 13:20:49 +02001323 pm_runtime_get_sync(dc->dev);
1324
1325 /* initialize display controller */
1326 if (dc->syncpt) {
1327 u32 syncpt = host1x_syncpt_id(dc->syncpt);
1328
1329 value = SYNCPT_CNTRL_NO_STALL;
1330 tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
1331
1332 value = SYNCPT_VSYNC_ENABLE | syncpt;
1333 tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
1334 }
1335
1336 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1337 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1338 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
1339
1340 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1341 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1342 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
1343
1344 /* initialize timer */
1345 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
1346 WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
1347 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
1348
1349 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
1350 WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
1351 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
1352
1353 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1354 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1355 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
1356
1357 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1358 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1359 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1360
Thierry Reding7116e9a2017-11-13 11:20:48 +01001361 if (dc->soc->supports_background_color)
1362 tegra_dc_writel(dc, 0, DC_DISP_BLEND_BACKGROUND_COLOR);
1363 else
Thierry Reding33a8eb82015-08-03 13:20:49 +02001364 tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);
1365
1366 /* apply PLL and pixel clock changes */
Thierry Reding76d59ed2014-12-19 15:09:16 +01001367 tegra_dc_commit_state(dc, state);
1368
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001369 /* program display mode */
1370 tegra_dc_set_timings(dc, mode);
1371
Thierry Reding8620fc62013-12-12 11:03:59 +01001372 /* interlacing isn't supported yet, so disable it */
1373 if (dc->soc->supports_interlacing) {
1374 value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
1375 value &= ~INTERLACE_ENABLE;
1376 tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
1377 }
Thierry Reding666cb872014-12-08 16:32:47 +01001378
1379 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
1380 value &= ~DISP_CTRL_MODE_MASK;
1381 value |= DISP_CTRL_MODE_C_DISPLAY;
1382 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
1383
1384 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
1385 value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
1386 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
1387 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
1388
1389 tegra_dc_commit(dc);
Thierry Reding23fb4742012-11-28 11:38:24 +01001390
Thierry Reding8ff64c12014-10-08 14:48:51 +02001391 drm_crtc_vblank_on(crtc);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001392}
1393
Thierry Reding4aa3df72014-11-24 16:27:13 +01001394static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
1395 struct drm_crtc_state *state)
1396{
Thierry Redingc4755fb2017-11-13 11:08:13 +01001397 struct tegra_atomic_state *s = to_tegra_atomic_state(state->state);
1398 struct tegra_dc_state *tegra = to_dc_state(state);
1399
1400 /*
1401 * The display hub display clock needs to be fed by the display clock
1402 * with the highest frequency to ensure proper functioning of all the
1403 * displays.
1404 *
1405 * Note that this isn't used before Tegra186, but it doesn't hurt and
1406 * conditionalizing it would make the code less clean.
1407 */
1408 if (state->active) {
1409 if (!s->clk_disp || tegra->pclk > s->rate) {
1410 s->dc = to_tegra_dc(crtc);
1411 s->clk_disp = s->dc->clk;
1412 s->rate = tegra->pclk;
1413 }
1414 }
1415
Thierry Reding4aa3df72014-11-24 16:27:13 +01001416 return 0;
1417}
1418
Maarten Lankhorst613d2b22015-07-21 13:28:58 +02001419static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
1420 struct drm_crtc_state *old_crtc_state)
Thierry Reding4aa3df72014-11-24 16:27:13 +01001421{
Thierry Reding9d99ab62017-10-12 17:40:46 +02001422 unsigned long flags;
Thierry Reding1503ca42014-11-24 17:41:23 +01001423
1424 if (crtc->state->event) {
Thierry Reding9d99ab62017-10-12 17:40:46 +02001425 spin_lock_irqsave(&crtc->dev->event_lock, flags);
Thierry Reding1503ca42014-11-24 17:41:23 +01001426
Thierry Reding9d99ab62017-10-12 17:40:46 +02001427 if (drm_crtc_vblank_get(crtc) != 0)
1428 drm_crtc_send_vblank_event(crtc, crtc->state->event);
1429 else
1430 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
Thierry Reding1503ca42014-11-24 17:41:23 +01001431
Thierry Reding9d99ab62017-10-12 17:40:46 +02001432 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
1433
Thierry Reding1503ca42014-11-24 17:41:23 +01001434 crtc->state->event = NULL;
1435 }
Thierry Reding4aa3df72014-11-24 16:27:13 +01001436}
1437
Maarten Lankhorst613d2b22015-07-21 13:28:58 +02001438static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
1439 struct drm_crtc_state *old_crtc_state)
Thierry Reding4aa3df72014-11-24 16:27:13 +01001440{
Thierry Reding47802b02014-11-26 12:28:39 +01001441 struct tegra_dc_state *state = to_dc_state(crtc->state);
1442 struct tegra_dc *dc = to_tegra_dc(crtc);
1443
1444 tegra_dc_writel(dc, state->planes << 8, DC_CMD_STATE_CONTROL);
1445 tegra_dc_writel(dc, state->planes, DC_CMD_STATE_CONTROL);
Thierry Reding4aa3df72014-11-24 16:27:13 +01001446}
1447
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001448static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
Thierry Reding4aa3df72014-11-24 16:27:13 +01001449 .atomic_check = tegra_crtc_atomic_check,
1450 .atomic_begin = tegra_crtc_atomic_begin,
1451 .atomic_flush = tegra_crtc_atomic_flush,
Laurent Pinchart0b20a0f2017-06-30 12:36:44 +03001452 .atomic_enable = tegra_crtc_atomic_enable,
Laurent Pinchart64581712017-06-30 12:36:45 +03001453 .atomic_disable = tegra_crtc_atomic_disable,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001454};
1455
Thierry Reding6e5ff992012-11-28 11:45:47 +01001456static irqreturn_t tegra_dc_irq(int irq, void *data)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001457{
1458 struct tegra_dc *dc = data;
1459 unsigned long status;
1460
1461 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
1462 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
1463
1464 if (status & FRAME_END_INT) {
1465 /*
1466 dev_dbg(dc->dev, "%s(): frame end\n", __func__);
1467 */
Thierry Reding791ddb12015-07-28 21:27:05 +02001468 dc->stats.frames++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001469 }
1470
1471 if (status & VBLANK_INT) {
1472 /*
1473 dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
1474 */
Thierry Redinged7dae52014-12-16 16:03:13 +01001475 drm_crtc_handle_vblank(&dc->base);
Thierry Reding791ddb12015-07-28 21:27:05 +02001476 dc->stats.vblank++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001477 }
1478
1479 if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
1480 /*
1481 dev_dbg(dc->dev, "%s(): underflow\n", __func__);
1482 */
Thierry Reding791ddb12015-07-28 21:27:05 +02001483 dc->stats.underflow++;
1484 }
1485
1486 if (status & (WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT)) {
1487 /*
1488 dev_dbg(dc->dev, "%s(): overflow\n", __func__);
1489 */
1490 dc->stats.overflow++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001491 }
1492
1493 return IRQ_HANDLED;
1494}
1495
Thierry Reding53fa7f72013-09-24 15:35:40 +02001496static int tegra_dc_init(struct host1x_client *client)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001497{
Thierry Reding9910f5c2014-05-22 09:57:15 +02001498 struct drm_device *drm = dev_get_drvdata(client->parent);
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001499 unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
Thierry Reding776dc382013-10-14 14:43:22 +02001500 struct tegra_dc *dc = host1x_client_to_dc(client);
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001501 struct tegra_drm *tegra = drm->dev_private;
Thierry Redingc7679302014-10-21 13:51:53 +02001502 struct drm_plane *primary = NULL;
1503 struct drm_plane *cursor = NULL;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001504 int err;
1505
Thierry Reding617dd7c2017-08-30 12:48:31 +02001506 dc->syncpt = host1x_syncpt_request(client, flags);
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001507 if (!dc->syncpt)
1508 dev_warn(dc->dev, "failed to allocate syncpoint\n");
1509
Thierry Redingdf06b752014-06-26 21:41:53 +02001510 if (tegra->domain) {
1511 err = iommu_attach_device(tegra->domain, dc->dev);
1512 if (err < 0) {
1513 dev_err(dc->dev, "failed to attach to domain: %d\n",
1514 err);
1515 return err;
1516 }
1517
1518 dc->domain = tegra->domain;
1519 }
1520
Thierry Redingc7679302014-10-21 13:51:53 +02001521 primary = tegra_dc_primary_plane_create(drm, dc);
1522 if (IS_ERR(primary)) {
1523 err = PTR_ERR(primary);
1524 goto cleanup;
1525 }
1526
1527 if (dc->soc->supports_cursor) {
1528 cursor = tegra_dc_cursor_plane_create(drm, dc);
1529 if (IS_ERR(cursor)) {
1530 err = PTR_ERR(cursor);
1531 goto cleanup;
1532 }
1533 }
1534
1535 err = drm_crtc_init_with_planes(drm, &dc->base, primary, cursor,
Ville Syrjäläf9882872015-12-09 16:19:31 +02001536 &tegra_crtc_funcs, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +02001537 if (err < 0)
1538 goto cleanup;
1539
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001540 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1541
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001542 /*
1543 * Keep track of the minimum pitch alignment across all display
1544 * controllers.
1545 */
1546 if (dc->soc->pitch_align > tegra->pitch_align)
1547 tegra->pitch_align = dc->soc->pitch_align;
1548
Thierry Reding9910f5c2014-05-22 09:57:15 +02001549 err = tegra_dc_rgb_init(drm, dc);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001550 if (err < 0 && err != -ENODEV) {
1551 dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
Thierry Redingc7679302014-10-21 13:51:53 +02001552 goto cleanup;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001553 }
1554
Thierry Reding9910f5c2014-05-22 09:57:15 +02001555 err = tegra_dc_add_planes(drm, dc);
Thierry Redingf34bc782012-11-04 21:47:13 +01001556 if (err < 0)
Thierry Redingc7679302014-10-21 13:51:53 +02001557 goto cleanup;
Thierry Redingf34bc782012-11-04 21:47:13 +01001558
Thierry Reding6e5ff992012-11-28 11:45:47 +01001559 err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001560 dev_name(dc->dev), dc);
1561 if (err < 0) {
1562 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
1563 err);
Thierry Redingc7679302014-10-21 13:51:53 +02001564 goto cleanup;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001565 }
1566
1567 return 0;
Thierry Redingc7679302014-10-21 13:51:53 +02001568
1569cleanup:
1570 if (cursor)
1571 drm_plane_cleanup(cursor);
1572
1573 if (primary)
1574 drm_plane_cleanup(primary);
1575
1576 if (tegra->domain) {
1577 iommu_detach_device(tegra->domain, dc->dev);
1578 dc->domain = NULL;
1579 }
1580
1581 return err;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001582}
1583
Thierry Reding53fa7f72013-09-24 15:35:40 +02001584static int tegra_dc_exit(struct host1x_client *client)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001585{
Thierry Reding776dc382013-10-14 14:43:22 +02001586 struct tegra_dc *dc = host1x_client_to_dc(client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001587 int err;
1588
1589 devm_free_irq(dc->dev, dc->irq, dc);
1590
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001591 err = tegra_dc_rgb_exit(dc);
1592 if (err) {
1593 dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
1594 return err;
1595 }
1596
Thierry Redingdf06b752014-06-26 21:41:53 +02001597 if (dc->domain) {
1598 iommu_detach_device(dc->domain, dc->dev);
1599 dc->domain = NULL;
1600 }
1601
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001602 host1x_syncpt_free(dc->syncpt);
1603
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001604 return 0;
1605}
1606
1607static const struct host1x_client_ops dc_client_ops = {
Thierry Reding53fa7f72013-09-24 15:35:40 +02001608 .init = tegra_dc_init,
1609 .exit = tegra_dc_exit,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001610};
1611
Thierry Reding8620fc62013-12-12 11:03:59 +01001612static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001613 .supports_background_color = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001614 .supports_interlacing = false,
Thierry Redinge6876512013-12-20 13:58:33 +01001615 .supports_cursor = false,
Thierry Redingc134f012014-06-03 14:48:12 +02001616 .supports_block_linear = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001617 .pitch_align = 8,
Thierry Reding9c012702014-07-07 15:32:53 +02001618 .has_powergate = false,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001619 .broken_reset = true,
Thierry Reding8620fc62013-12-12 11:03:59 +01001620};
1621
1622static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001623 .supports_background_color = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001624 .supports_interlacing = false,
Thierry Redinge6876512013-12-20 13:58:33 +01001625 .supports_cursor = false,
Thierry Redingc134f012014-06-03 14:48:12 +02001626 .supports_block_linear = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001627 .pitch_align = 8,
Thierry Reding9c012702014-07-07 15:32:53 +02001628 .has_powergate = false,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001629 .broken_reset = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001630};
1631
1632static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001633 .supports_background_color = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001634 .supports_interlacing = false,
1635 .supports_cursor = false,
1636 .supports_block_linear = false,
1637 .pitch_align = 64,
Thierry Reding9c012702014-07-07 15:32:53 +02001638 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001639 .broken_reset = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001640};
1641
1642static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001643 .supports_background_color = true,
Thierry Reding8620fc62013-12-12 11:03:59 +01001644 .supports_interlacing = true,
Thierry Redinge6876512013-12-20 13:58:33 +01001645 .supports_cursor = true,
Thierry Redingc134f012014-06-03 14:48:12 +02001646 .supports_block_linear = true,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001647 .pitch_align = 64,
Thierry Reding9c012702014-07-07 15:32:53 +02001648 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001649 .broken_reset = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001650};
1651
Thierry Reding5b4f5162015-03-27 10:31:58 +01001652static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001653 .supports_background_color = true,
Thierry Reding5b4f5162015-03-27 10:31:58 +01001654 .supports_interlacing = true,
1655 .supports_cursor = true,
1656 .supports_block_linear = true,
1657 .pitch_align = 64,
1658 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001659 .broken_reset = false,
Thierry Reding5b4f5162015-03-27 10:31:58 +01001660};
1661
Thierry Reding8620fc62013-12-12 11:03:59 +01001662static const struct of_device_id tegra_dc_of_match[] = {
1663 {
Thierry Reding5b4f5162015-03-27 10:31:58 +01001664 .compatible = "nvidia,tegra210-dc",
1665 .data = &tegra210_dc_soc_info,
1666 }, {
Thierry Reding8620fc62013-12-12 11:03:59 +01001667 .compatible = "nvidia,tegra124-dc",
1668 .data = &tegra124_dc_soc_info,
1669 }, {
Thierry Reding9c012702014-07-07 15:32:53 +02001670 .compatible = "nvidia,tegra114-dc",
1671 .data = &tegra114_dc_soc_info,
1672 }, {
Thierry Reding8620fc62013-12-12 11:03:59 +01001673 .compatible = "nvidia,tegra30-dc",
1674 .data = &tegra30_dc_soc_info,
1675 }, {
1676 .compatible = "nvidia,tegra20-dc",
1677 .data = &tegra20_dc_soc_info,
1678 }, {
1679 /* sentinel */
1680 }
1681};
Stephen Warrenef707282014-06-18 16:21:55 -06001682MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
Thierry Reding8620fc62013-12-12 11:03:59 +01001683
Thierry Reding13411dd2014-01-09 17:08:36 +01001684static int tegra_dc_parse_dt(struct tegra_dc *dc)
1685{
1686 struct device_node *np;
1687 u32 value = 0;
1688 int err;
1689
1690 err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);
1691 if (err < 0) {
1692 dev_err(dc->dev, "missing \"nvidia,head\" property\n");
1693
1694 /*
1695 * If the nvidia,head property isn't present, try to find the
1696 * correct head number by looking up the position of this
1697 * display controller's node within the device tree. Assuming
1698 * that the nodes are ordered properly in the DTS file and
1699 * that the translation into a flattened device tree blob
1700 * preserves that ordering this will actually yield the right
1701 * head number.
1702 *
1703 * If those assumptions don't hold, this will still work for
1704 * cases where only a single display controller is used.
1705 */
1706 for_each_matching_node(np, tegra_dc_of_match) {
Julia Lawallcf6b1742015-10-24 16:42:31 +02001707 if (np == dc->dev->of_node) {
1708 of_node_put(np);
Thierry Reding13411dd2014-01-09 17:08:36 +01001709 break;
Julia Lawallcf6b1742015-10-24 16:42:31 +02001710 }
Thierry Reding13411dd2014-01-09 17:08:36 +01001711
1712 value++;
1713 }
1714 }
1715
1716 dc->pipe = value;
1717
1718 return 0;
1719}
1720
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001721static int tegra_dc_probe(struct platform_device *pdev)
1722{
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001723 struct resource *regs;
1724 struct tegra_dc *dc;
1725 int err;
1726
1727 dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
1728 if (!dc)
1729 return -ENOMEM;
1730
Thierry Redingb9ff7ae2017-08-21 16:35:17 +02001731 dc->soc = of_device_get_match_data(&pdev->dev);
Thierry Reding8620fc62013-12-12 11:03:59 +01001732
Thierry Reding6e5ff992012-11-28 11:45:47 +01001733 spin_lock_init(&dc->lock);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001734 INIT_LIST_HEAD(&dc->list);
1735 dc->dev = &pdev->dev;
1736
Thierry Reding13411dd2014-01-09 17:08:36 +01001737 err = tegra_dc_parse_dt(dc);
1738 if (err < 0)
1739 return err;
1740
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001741 dc->clk = devm_clk_get(&pdev->dev, NULL);
1742 if (IS_ERR(dc->clk)) {
1743 dev_err(&pdev->dev, "failed to get clock\n");
1744 return PTR_ERR(dc->clk);
1745 }
1746
Stephen Warrenca480802013-11-06 16:20:54 -07001747 dc->rst = devm_reset_control_get(&pdev->dev, "dc");
1748 if (IS_ERR(dc->rst)) {
1749 dev_err(&pdev->dev, "failed to get reset\n");
1750 return PTR_ERR(dc->rst);
1751 }
1752
Thierry Redinga2f2f742017-08-30 17:41:00 +02001753 /* assert reset and disable clock */
1754 if (!dc->soc->broken_reset) {
1755 err = clk_prepare_enable(dc->clk);
1756 if (err < 0)
1757 return err;
1758
1759 usleep_range(2000, 4000);
1760
1761 err = reset_control_assert(dc->rst);
1762 if (err < 0)
1763 return err;
1764
1765 usleep_range(2000, 4000);
1766
1767 clk_disable_unprepare(dc->clk);
1768 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02001769
Thierry Reding9c012702014-07-07 15:32:53 +02001770 if (dc->soc->has_powergate) {
1771 if (dc->pipe == 0)
1772 dc->powergate = TEGRA_POWERGATE_DIS;
1773 else
1774 dc->powergate = TEGRA_POWERGATE_DISB;
1775
Thierry Reding33a8eb82015-08-03 13:20:49 +02001776 tegra_powergate_power_off(dc->powergate);
Thierry Reding9c012702014-07-07 15:32:53 +02001777 }
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001778
1779 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Thierry Redingd4ed6022013-01-21 11:09:02 +01001780 dc->regs = devm_ioremap_resource(&pdev->dev, regs);
1781 if (IS_ERR(dc->regs))
1782 return PTR_ERR(dc->regs);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001783
1784 dc->irq = platform_get_irq(pdev, 0);
1785 if (dc->irq < 0) {
1786 dev_err(&pdev->dev, "failed to get IRQ\n");
1787 return -ENXIO;
1788 }
1789
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001790 err = tegra_dc_rgb_probe(dc);
1791 if (err < 0 && err != -ENODEV) {
1792 dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
1793 return err;
1794 }
1795
Thierry Reding33a8eb82015-08-03 13:20:49 +02001796 platform_set_drvdata(pdev, dc);
1797 pm_runtime_enable(&pdev->dev);
1798
1799 INIT_LIST_HEAD(&dc->client.list);
1800 dc->client.ops = &dc_client_ops;
1801 dc->client.dev = &pdev->dev;
1802
Thierry Reding776dc382013-10-14 14:43:22 +02001803 err = host1x_client_register(&dc->client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001804 if (err < 0) {
1805 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1806 err);
1807 return err;
1808 }
1809
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001810 return 0;
1811}
1812
1813static int tegra_dc_remove(struct platform_device *pdev)
1814{
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001815 struct tegra_dc *dc = platform_get_drvdata(pdev);
1816 int err;
1817
Thierry Reding776dc382013-10-14 14:43:22 +02001818 err = host1x_client_unregister(&dc->client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001819 if (err < 0) {
1820 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1821 err);
1822 return err;
1823 }
1824
Thierry Reding59d29c02013-10-14 14:26:42 +02001825 err = tegra_dc_rgb_remove(dc);
1826 if (err < 0) {
1827 dev_err(&pdev->dev, "failed to remove RGB output: %d\n", err);
1828 return err;
1829 }
1830
Thierry Reding33a8eb82015-08-03 13:20:49 +02001831 pm_runtime_disable(&pdev->dev);
1832
1833 return 0;
1834}
1835
1836#ifdef CONFIG_PM
1837static int tegra_dc_suspend(struct device *dev)
1838{
1839 struct tegra_dc *dc = dev_get_drvdata(dev);
1840 int err;
1841
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001842 if (!dc->soc->broken_reset) {
1843 err = reset_control_assert(dc->rst);
1844 if (err < 0) {
1845 dev_err(dev, "failed to assert reset: %d\n", err);
1846 return err;
1847 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02001848 }
Thierry Reding9c012702014-07-07 15:32:53 +02001849
1850 if (dc->soc->has_powergate)
1851 tegra_powergate_power_off(dc->powergate);
1852
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001853 clk_disable_unprepare(dc->clk);
1854
1855 return 0;
1856}
1857
Thierry Reding33a8eb82015-08-03 13:20:49 +02001858static int tegra_dc_resume(struct device *dev)
1859{
1860 struct tegra_dc *dc = dev_get_drvdata(dev);
1861 int err;
1862
1863 if (dc->soc->has_powergate) {
1864 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
1865 dc->rst);
1866 if (err < 0) {
1867 dev_err(dev, "failed to power partition: %d\n", err);
1868 return err;
1869 }
1870 } else {
1871 err = clk_prepare_enable(dc->clk);
1872 if (err < 0) {
1873 dev_err(dev, "failed to enable clock: %d\n", err);
1874 return err;
1875 }
1876
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001877 if (!dc->soc->broken_reset) {
1878 err = reset_control_deassert(dc->rst);
1879 if (err < 0) {
1880 dev_err(dev,
1881 "failed to deassert reset: %d\n", err);
1882 return err;
1883 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02001884 }
1885 }
1886
1887 return 0;
1888}
1889#endif
1890
1891static const struct dev_pm_ops tegra_dc_pm_ops = {
1892 SET_RUNTIME_PM_OPS(tegra_dc_suspend, tegra_dc_resume, NULL)
1893};
1894
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001895struct platform_driver tegra_dc_driver = {
1896 .driver = {
1897 .name = "tegra-dc",
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001898 .of_match_table = tegra_dc_of_match,
Thierry Reding33a8eb82015-08-03 13:20:49 +02001899 .pm = &tegra_dc_pm_ops,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001900 },
1901 .probe = tegra_dc_probe,
1902 .remove = tegra_dc_remove,
1903};