blob: 6790e2d869c4971ee39458c5f4642d9b35793d48 [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 Reding47307952017-08-30 17:42:54 +020022#include "hub.h"
Thierry Reding5acd3512017-11-10 15:27:25 +010023#include "plane.h"
Thierry Redingd8f4a9e2012-11-15 21:28:22 +000024
Thierry Reding9d441892014-11-24 17:02:53 +010025#include <drm/drm_atomic.h>
Thierry Reding4aa3df72014-11-24 16:27:13 +010026#include <drm/drm_atomic_helper.h>
Daniel Vetter3cb9ae42014-10-29 10:03:57 +010027#include <drm/drm_plane_helper.h>
28
Thierry Reding791ddb12015-07-28 21:27:05 +020029static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)
30{
31 stats->frames = 0;
32 stats->vblank = 0;
33 stats->underflow = 0;
34 stats->overflow = 0;
35}
36
Thierry Redingd700ba72014-12-08 15:50:04 +010037/*
Thierry Reding86df2562014-12-08 16:03:53 +010038 * Reads the active copy of a register. This takes the dc->lock spinlock to
39 * prevent races with the VBLANK processing which also needs access to the
40 * active copy of some registers.
41 */
42static u32 tegra_dc_readl_active(struct tegra_dc *dc, unsigned long offset)
43{
44 unsigned long flags;
45 u32 value;
46
47 spin_lock_irqsave(&dc->lock, flags);
48
49 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
50 value = tegra_dc_readl(dc, offset);
51 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
52
53 spin_unlock_irqrestore(&dc->lock, flags);
54 return value;
55}
56
57/*
Thierry Redingd700ba72014-12-08 15:50:04 +010058 * Double-buffered registers have two copies: ASSEMBLY and ACTIVE. When the
59 * *_ACT_REQ bits are set the ASSEMBLY copy is latched into the ACTIVE copy.
60 * Latching happens mmediately if the display controller is in STOP mode or
61 * on the next frame boundary otherwise.
62 *
63 * Triple-buffered registers have three copies: ASSEMBLY, ARM and ACTIVE. The
64 * ASSEMBLY copy is latched into the ARM copy immediately after *_UPDATE bits
65 * are written. When the *_ACT_REQ bits are written, the ARM copy is latched
66 * into the ACTIVE copy, either immediately if the display controller is in
67 * STOP mode, or at the next frame boundary otherwise.
68 */
Thierry Reding62b9e062014-11-21 17:33:33 +010069void tegra_dc_commit(struct tegra_dc *dc)
Thierry Reding205d48e2014-10-21 13:41:46 +020070{
71 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
72 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
73}
74
Thierry Reding10288ee2014-03-14 09:54:58 +010075static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
76 unsigned int bpp)
77{
78 fixed20_12 outf = dfixed_init(out);
79 fixed20_12 inf = dfixed_init(in);
80 u32 dda_inc;
81 int max;
82
83 if (v)
84 max = 15;
85 else {
86 switch (bpp) {
87 case 2:
88 max = 8;
89 break;
90
91 default:
92 WARN_ON_ONCE(1);
93 /* fallthrough */
94 case 4:
95 max = 4;
96 break;
97 }
98 }
99
100 outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
101 inf.full -= dfixed_const(1);
102
103 dda_inc = dfixed_div(inf, outf);
104 dda_inc = min_t(u32, dda_inc, dfixed_const(max));
105
106 return dda_inc;
107}
108
109static inline u32 compute_initial_dda(unsigned int in)
110{
111 fixed20_12 inf = dfixed_init(in);
112 return dfixed_frac(inf);
113}
114
Thierry Reding4aa3df72014-11-24 16:27:13 +0100115static void tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
116 const struct tegra_dc_window *window)
Thierry Reding10288ee2014-03-14 09:54:58 +0100117{
118 unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
Sean Paul93396d02014-11-19 13:04:49 -0500119 unsigned long value, flags;
Thierry Reding10288ee2014-03-14 09:54:58 +0100120 bool yuv, planar;
121
122 /*
123 * For YUV planar modes, the number of bytes per pixel takes into
124 * account only the luma component and therefore is 1.
125 */
Thierry Reding5acd3512017-11-10 15:27:25 +0100126 yuv = tegra_plane_format_is_yuv(window->format, &planar);
Thierry Reding10288ee2014-03-14 09:54:58 +0100127 if (!yuv)
128 bpp = window->bits_per_pixel / 8;
129 else
130 bpp = planar ? 1 : 2;
131
Sean Paul93396d02014-11-19 13:04:49 -0500132 spin_lock_irqsave(&dc->lock, flags);
133
Thierry Reding10288ee2014-03-14 09:54:58 +0100134 value = WINDOW_A_SELECT << index;
135 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
136
137 tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
138 tegra_dc_writel(dc, window->swap, DC_WIN_BYTE_SWAP);
139
140 value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
141 tegra_dc_writel(dc, value, DC_WIN_POSITION);
142
143 value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
144 tegra_dc_writel(dc, value, DC_WIN_SIZE);
145
146 h_offset = window->src.x * bpp;
147 v_offset = window->src.y;
148 h_size = window->src.w * bpp;
149 v_size = window->src.h;
150
151 value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
152 tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
153
154 /*
155 * For DDA computations the number of bytes per pixel for YUV planar
156 * modes needs to take into account all Y, U and V components.
157 */
158 if (yuv && planar)
159 bpp = 2;
160
161 h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
162 v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
163
164 value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
165 tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
166
167 h_dda = compute_initial_dda(window->src.x);
168 v_dda = compute_initial_dda(window->src.y);
169
170 tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
171 tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
172
173 tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
174 tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
175
176 tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
177
178 if (yuv && planar) {
179 tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
180 tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
181 value = window->stride[1] << 16 | window->stride[0];
182 tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
183 } else {
184 tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
185 }
186
187 if (window->bottom_up)
188 v_offset += window->src.h - 1;
189
190 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
191 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
192
Thierry Redingc134f012014-06-03 14:48:12 +0200193 if (dc->soc->supports_block_linear) {
194 unsigned long height = window->tiling.value;
Thierry Reding10288ee2014-03-14 09:54:58 +0100195
Thierry Redingc134f012014-06-03 14:48:12 +0200196 switch (window->tiling.mode) {
197 case TEGRA_BO_TILING_MODE_PITCH:
198 value = DC_WINBUF_SURFACE_KIND_PITCH;
199 break;
200
201 case TEGRA_BO_TILING_MODE_TILED:
202 value = DC_WINBUF_SURFACE_KIND_TILED;
203 break;
204
205 case TEGRA_BO_TILING_MODE_BLOCK:
206 value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
207 DC_WINBUF_SURFACE_KIND_BLOCK;
208 break;
209 }
210
211 tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
212 } else {
213 switch (window->tiling.mode) {
214 case TEGRA_BO_TILING_MODE_PITCH:
215 value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
216 DC_WIN_BUFFER_ADDR_MODE_LINEAR;
217 break;
218
219 case TEGRA_BO_TILING_MODE_TILED:
220 value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
221 DC_WIN_BUFFER_ADDR_MODE_TILE;
222 break;
223
224 case TEGRA_BO_TILING_MODE_BLOCK:
Thierry Reding4aa3df72014-11-24 16:27:13 +0100225 /*
226 * No need to handle this here because ->atomic_check
227 * will already have filtered it out.
228 */
229 break;
Thierry Redingc134f012014-06-03 14:48:12 +0200230 }
231
232 tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
233 }
Thierry Reding10288ee2014-03-14 09:54:58 +0100234
235 value = WIN_ENABLE;
236
237 if (yuv) {
238 /* setup default colorspace conversion coefficients */
239 tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
240 tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
241 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
242 tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
243 tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
244 tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
245 tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
246 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
247
248 value |= CSC_ENABLE;
249 } else if (window->bits_per_pixel < 24) {
250 value |= COLOR_EXPAND;
251 }
252
253 if (window->bottom_up)
254 value |= V_DIRECTION;
255
256 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
257
258 /*
259 * Disable blending and assume Window A is the bottom-most window,
260 * Window C is the top-most window and Window B is in the middle.
261 */
262 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
263 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
264
265 switch (index) {
266 case 0:
267 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
268 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
269 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
270 break;
271
272 case 1:
273 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
274 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
275 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
276 break;
277
278 case 2:
279 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
280 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
281 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
282 break;
283 }
284
Sean Paul93396d02014-11-19 13:04:49 -0500285 spin_unlock_irqrestore(&dc->lock, flags);
Thierry Redingc7679302014-10-21 13:51:53 +0200286}
287
Thierry Redingc7679302014-10-21 13:51:53 +0200288static const u32 tegra_primary_plane_formats[] = {
289 DRM_FORMAT_XBGR8888,
Thierry Reding7772fda2017-10-12 17:30:55 +0200290 DRM_FORMAT_ABGR8888,
Thierry Redingc7679302014-10-21 13:51:53 +0200291 DRM_FORMAT_XRGB8888,
Thierry Reding7772fda2017-10-12 17:30:55 +0200292 DRM_FORMAT_ARGB8888,
Thierry Redingc7679302014-10-21 13:51:53 +0200293 DRM_FORMAT_RGB565,
294};
295
Thierry Reding4aa3df72014-11-24 16:27:13 +0100296static int tegra_plane_atomic_check(struct drm_plane *plane,
297 struct drm_plane_state *state)
298{
Thierry Reding8f604f82014-11-28 13:14:55 +0100299 struct tegra_plane_state *plane_state = to_tegra_plane_state(state);
300 struct tegra_bo_tiling *tiling = &plane_state->tiling;
Thierry Reding47802b02014-11-26 12:28:39 +0100301 struct tegra_plane *tegra = to_tegra_plane(plane);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100302 struct tegra_dc *dc = to_tegra_dc(state->crtc);
Thierry Redingc7679302014-10-21 13:51:53 +0200303 int err;
304
Thierry Reding4aa3df72014-11-24 16:27:13 +0100305 /* no need for further checks if the plane is being disabled */
306 if (!state->crtc)
307 return 0;
308
Thierry Reding5acd3512017-11-10 15:27:25 +0100309 err = tegra_plane_format(state->fb->format->format,
310 &plane_state->format,
311 &plane_state->swap);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100312 if (err < 0)
313 return err;
314
Thierry Reding8f604f82014-11-28 13:14:55 +0100315 err = tegra_fb_get_tiling(state->fb, tiling);
316 if (err < 0)
317 return err;
318
319 if (tiling->mode == TEGRA_BO_TILING_MODE_BLOCK &&
Thierry Reding4aa3df72014-11-24 16:27:13 +0100320 !dc->soc->supports_block_linear) {
321 DRM_ERROR("hardware doesn't support block linear mode\n");
322 return -EINVAL;
323 }
324
325 /*
326 * Tegra doesn't support different strides for U and V planes so we
327 * error out if the user tries to display a framebuffer with such a
328 * configuration.
329 */
Ville Syrjäläbcb0b462016-12-14 23:30:22 +0200330 if (state->fb->format->num_planes > 2) {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100331 if (state->fb->pitches[2] != state->fb->pitches[1]) {
332 DRM_ERROR("unsupported UV-plane configuration\n");
333 return -EINVAL;
334 }
335 }
336
Thierry Reding47802b02014-11-26 12:28:39 +0100337 err = tegra_plane_state_add(tegra, state);
338 if (err < 0)
339 return err;
340
Thierry Reding4aa3df72014-11-24 16:27:13 +0100341 return 0;
342}
343
Thierry Redinga4bfa092017-08-30 17:34:10 +0200344static void tegra_plane_atomic_disable(struct drm_plane *plane,
345 struct drm_plane_state *old_state)
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300346{
Thierry Redinga4bfa092017-08-30 17:34:10 +0200347 struct tegra_dc *dc = to_tegra_dc(old_state->crtc);
348 struct tegra_plane *p = to_tegra_plane(plane);
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300349 unsigned long flags;
350 u32 value;
351
Thierry Redinga4bfa092017-08-30 17:34:10 +0200352 /* rien ne va plus */
353 if (!old_state || !old_state->crtc)
354 return;
355
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300356 spin_lock_irqsave(&dc->lock, flags);
357
Thierry Redinga4bfa092017-08-30 17:34:10 +0200358 value = WINDOW_A_SELECT << p->index;
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300359 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
360
361 value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
362 value &= ~WIN_ENABLE;
363 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
364
365 spin_unlock_irqrestore(&dc->lock, flags);
366}
367
Thierry Reding4aa3df72014-11-24 16:27:13 +0100368static void tegra_plane_atomic_update(struct drm_plane *plane,
369 struct drm_plane_state *old_state)
370{
Thierry Reding8f604f82014-11-28 13:14:55 +0100371 struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100372 struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
373 struct drm_framebuffer *fb = plane->state->fb;
374 struct tegra_plane *p = to_tegra_plane(plane);
375 struct tegra_dc_window window;
376 unsigned int i;
Thierry Reding4aa3df72014-11-24 16:27:13 +0100377
378 /* rien ne va plus */
379 if (!plane->state->crtc || !plane->state->fb)
380 return;
381
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300382 if (!plane->state->visible)
Thierry Redinga4bfa092017-08-30 17:34:10 +0200383 return tegra_plane_atomic_disable(plane, old_state);
Dmitry Osipenko80d3eef2017-06-15 02:18:31 +0300384
Thierry Redingc7679302014-10-21 13:51:53 +0200385 memset(&window, 0, sizeof(window));
Dmitry Osipenko7d205852017-06-15 02:18:30 +0300386 window.src.x = plane->state->src.x1 >> 16;
387 window.src.y = plane->state->src.y1 >> 16;
388 window.src.w = drm_rect_width(&plane->state->src) >> 16;
389 window.src.h = drm_rect_height(&plane->state->src) >> 16;
390 window.dst.x = plane->state->dst.x1;
391 window.dst.y = plane->state->dst.y1;
392 window.dst.w = drm_rect_width(&plane->state->dst);
393 window.dst.h = drm_rect_height(&plane->state->dst);
Ville Syrjälä272725c2016-12-14 23:32:20 +0200394 window.bits_per_pixel = fb->format->cpp[0] * 8;
Thierry Redingc7679302014-10-21 13:51:53 +0200395 window.bottom_up = tegra_fb_is_bottom_up(fb);
396
Thierry Reding8f604f82014-11-28 13:14:55 +0100397 /* copy from state */
398 window.tiling = state->tiling;
399 window.format = state->format;
400 window.swap = state->swap;
Thierry Redingc7679302014-10-21 13:51:53 +0200401
Ville Syrjäläbcb0b462016-12-14 23:30:22 +0200402 for (i = 0; i < fb->format->num_planes; i++) {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100403 struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
Thierry Redingc7679302014-10-21 13:51:53 +0200404
Thierry Reding4aa3df72014-11-24 16:27:13 +0100405 window.base[i] = bo->paddr + fb->offsets[i];
Dmitry Osipenko08ee0172016-08-21 11:57:58 +0300406
407 /*
408 * Tegra uses a shared stride for UV planes. Framebuffers are
409 * already checked for this in the tegra_plane_atomic_check()
410 * function, so it's safe to ignore the V-plane pitch here.
411 */
412 if (i < 2)
413 window.stride[i] = fb->pitches[i];
Thierry Reding4aa3df72014-11-24 16:27:13 +0100414 }
Thierry Redingc7679302014-10-21 13:51:53 +0200415
Thierry Reding4aa3df72014-11-24 16:27:13 +0100416 tegra_dc_setup_window(dc, p->index, &window);
Thierry Redingc7679302014-10-21 13:51:53 +0200417}
418
Thierry Redinga4bfa092017-08-30 17:34:10 +0200419static const struct drm_plane_helper_funcs tegra_plane_helper_funcs = {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100420 .atomic_check = tegra_plane_atomic_check,
Thierry Reding4aa3df72014-11-24 16:27:13 +0100421 .atomic_disable = tegra_plane_atomic_disable,
Thierry Redinga4bfa092017-08-30 17:34:10 +0200422 .atomic_update = tegra_plane_atomic_update,
Thierry Redingc7679302014-10-21 13:51:53 +0200423};
424
Thierry Reding47307952017-08-30 17:42:54 +0200425static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
426 struct tegra_dc *dc)
Thierry Redingc7679302014-10-21 13:51:53 +0200427{
Thierry Reding518e6222014-12-16 18:04:08 +0100428 /*
429 * Ideally this would use drm_crtc_mask(), but that would require the
430 * CRTC to already be in the mode_config's list of CRTCs. However, it
431 * will only be added to that list in the drm_crtc_init_with_planes()
432 * (in tegra_dc_init()), which in turn requires registration of these
433 * planes. So we have ourselves a nice little chicken and egg problem
434 * here.
435 *
436 * We work around this by manually creating the mask from the number
437 * of CRTCs that have been registered, and should therefore always be
438 * the same as drm_crtc_index() after registration.
439 */
440 unsigned long possible_crtcs = 1 << drm->mode_config.num_crtc;
Thierry Reding47307952017-08-30 17:42:54 +0200441 enum drm_plane_type type = DRM_PLANE_TYPE_PRIMARY;
Thierry Redingc7679302014-10-21 13:51:53 +0200442 struct tegra_plane *plane;
443 unsigned int num_formats;
444 const u32 *formats;
445 int err;
446
447 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
448 if (!plane)
449 return ERR_PTR(-ENOMEM);
450
451 num_formats = ARRAY_SIZE(tegra_primary_plane_formats);
452 formats = tegra_primary_plane_formats;
453
Thierry Redingc4755fb2017-11-13 11:08:13 +0100454 /*
455 * XXX compute offset so that we can directly access windows.
456 *
457 * Always use window A as primary window.
458 */
459 plane->offset = 0;
460 plane->index = 0;
461 plane->depth = 255;
462
Thierry Reding518e6222014-12-16 18:04:08 +0100463 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
Thierry Redingc1cb4b62017-08-30 18:04:12 +0200464 &tegra_plane_funcs, formats,
Thierry Reding47307952017-08-30 17:42:54 +0200465 num_formats, NULL, type, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200466 if (err < 0) {
467 kfree(plane);
468 return ERR_PTR(err);
469 }
470
Thierry Redinga4bfa092017-08-30 17:34:10 +0200471 drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100472
Thierry Redingc7679302014-10-21 13:51:53 +0200473 return &plane->base;
474}
475
476static const u32 tegra_cursor_plane_formats[] = {
477 DRM_FORMAT_RGBA8888,
478};
479
Thierry Reding4aa3df72014-11-24 16:27:13 +0100480static int tegra_cursor_atomic_check(struct drm_plane *plane,
481 struct drm_plane_state *state)
Thierry Redingc7679302014-10-21 13:51:53 +0200482{
Thierry Reding47802b02014-11-26 12:28:39 +0100483 struct tegra_plane *tegra = to_tegra_plane(plane);
484 int err;
485
Thierry Reding4aa3df72014-11-24 16:27:13 +0100486 /* no need for further checks if the plane is being disabled */
487 if (!state->crtc)
488 return 0;
Thierry Redingc7679302014-10-21 13:51:53 +0200489
490 /* scaling not supported for cursor */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100491 if ((state->src_w >> 16 != state->crtc_w) ||
492 (state->src_h >> 16 != state->crtc_h))
Thierry Redingc7679302014-10-21 13:51:53 +0200493 return -EINVAL;
494
495 /* only square cursors supported */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100496 if (state->src_w != state->src_h)
Thierry Redingc7679302014-10-21 13:51:53 +0200497 return -EINVAL;
498
Thierry Reding4aa3df72014-11-24 16:27:13 +0100499 if (state->crtc_w != 32 && state->crtc_w != 64 &&
500 state->crtc_w != 128 && state->crtc_w != 256)
501 return -EINVAL;
502
Thierry Reding47802b02014-11-26 12:28:39 +0100503 err = tegra_plane_state_add(tegra, state);
504 if (err < 0)
505 return err;
506
Thierry Reding4aa3df72014-11-24 16:27:13 +0100507 return 0;
508}
509
510static void tegra_cursor_atomic_update(struct drm_plane *plane,
511 struct drm_plane_state *old_state)
512{
513 struct tegra_bo *bo = tegra_fb_get_plane(plane->state->fb, 0);
514 struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
515 struct drm_plane_state *state = plane->state;
516 u32 value = CURSOR_CLIP_DISPLAY;
517
518 /* rien ne va plus */
519 if (!plane->state->crtc || !plane->state->fb)
520 return;
521
522 switch (state->crtc_w) {
Thierry Redingc7679302014-10-21 13:51:53 +0200523 case 32:
524 value |= CURSOR_SIZE_32x32;
525 break;
526
527 case 64:
528 value |= CURSOR_SIZE_64x64;
529 break;
530
531 case 128:
532 value |= CURSOR_SIZE_128x128;
533 break;
534
535 case 256:
536 value |= CURSOR_SIZE_256x256;
537 break;
538
539 default:
Thierry Reding4aa3df72014-11-24 16:27:13 +0100540 WARN(1, "cursor size %ux%u not supported\n", state->crtc_w,
541 state->crtc_h);
542 return;
Thierry Redingc7679302014-10-21 13:51:53 +0200543 }
544
545 value |= (bo->paddr >> 10) & 0x3fffff;
546 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
547
548#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
549 value = (bo->paddr >> 32) & 0x3;
550 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
551#endif
552
553 /* enable cursor and set blend mode */
554 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
555 value |= CURSOR_ENABLE;
556 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
557
558 value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
559 value &= ~CURSOR_DST_BLEND_MASK;
560 value &= ~CURSOR_SRC_BLEND_MASK;
561 value |= CURSOR_MODE_NORMAL;
562 value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC;
563 value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
564 value |= CURSOR_ALPHA;
565 tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
566
567 /* position the cursor */
Thierry Reding4aa3df72014-11-24 16:27:13 +0100568 value = (state->crtc_y & 0x3fff) << 16 | (state->crtc_x & 0x3fff);
Thierry Redingc7679302014-10-21 13:51:53 +0200569 tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
Thierry Redingc7679302014-10-21 13:51:53 +0200570}
571
Thierry Reding4aa3df72014-11-24 16:27:13 +0100572static void tegra_cursor_atomic_disable(struct drm_plane *plane,
573 struct drm_plane_state *old_state)
Thierry Redingc7679302014-10-21 13:51:53 +0200574{
Thierry Reding4aa3df72014-11-24 16:27:13 +0100575 struct tegra_dc *dc;
Thierry Redingc7679302014-10-21 13:51:53 +0200576 u32 value;
577
Thierry Reding4aa3df72014-11-24 16:27:13 +0100578 /* rien ne va plus */
579 if (!old_state || !old_state->crtc)
580 return;
581
582 dc = to_tegra_dc(old_state->crtc);
Thierry Redingc7679302014-10-21 13:51:53 +0200583
584 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
585 value &= ~CURSOR_ENABLE;
586 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
Thierry Redingc7679302014-10-21 13:51:53 +0200587}
588
Thierry Reding4aa3df72014-11-24 16:27:13 +0100589static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {
Thierry Reding4aa3df72014-11-24 16:27:13 +0100590 .atomic_check = tegra_cursor_atomic_check,
591 .atomic_update = tegra_cursor_atomic_update,
592 .atomic_disable = tegra_cursor_atomic_disable,
Thierry Redingc7679302014-10-21 13:51:53 +0200593};
594
595static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
596 struct tegra_dc *dc)
597{
598 struct tegra_plane *plane;
599 unsigned int num_formats;
600 const u32 *formats;
601 int err;
602
603 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
604 if (!plane)
605 return ERR_PTR(-ENOMEM);
606
Thierry Reding47802b02014-11-26 12:28:39 +0100607 /*
Thierry Redinga1df3b22015-07-21 16:42:30 +0200608 * This index is kind of fake. The cursor isn't a regular plane, but
609 * its update and activation request bits in DC_CMD_STATE_CONTROL do
610 * use the same programming. Setting this fake index here allows the
611 * code in tegra_add_plane_state() to do the right thing without the
612 * need to special-casing the cursor plane.
Thierry Reding47802b02014-11-26 12:28:39 +0100613 */
614 plane->index = 6;
615
Thierry Redingc7679302014-10-21 13:51:53 +0200616 num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
617 formats = tegra_cursor_plane_formats;
618
619 err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
Thierry Redingc1cb4b62017-08-30 18:04:12 +0200620 &tegra_plane_funcs, formats,
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700621 num_formats, NULL,
622 DRM_PLANE_TYPE_CURSOR, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200623 if (err < 0) {
624 kfree(plane);
625 return ERR_PTR(err);
626 }
627
Thierry Reding4aa3df72014-11-24 16:27:13 +0100628 drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs);
629
Thierry Redingc7679302014-10-21 13:51:53 +0200630 return &plane->base;
631}
632
Thierry Redingc7679302014-10-21 13:51:53 +0200633static const uint32_t tegra_overlay_plane_formats[] = {
Thierry Redingdbe4d9a2013-03-22 15:37:30 +0100634 DRM_FORMAT_XBGR8888,
Thierry Reding7772fda2017-10-12 17:30:55 +0200635 DRM_FORMAT_ABGR8888,
Thierry Redingf34bc782012-11-04 21:47:13 +0100636 DRM_FORMAT_XRGB8888,
Thierry Reding7772fda2017-10-12 17:30:55 +0200637 DRM_FORMAT_ARGB8888,
Thierry Redingdbe4d9a2013-03-22 15:37:30 +0100638 DRM_FORMAT_RGB565,
Thierry Redingf34bc782012-11-04 21:47:13 +0100639 DRM_FORMAT_UYVY,
Thierry Redingf9253902014-01-29 20:31:17 +0100640 DRM_FORMAT_YUYV,
Thierry Redingf34bc782012-11-04 21:47:13 +0100641 DRM_FORMAT_YUV420,
642 DRM_FORMAT_YUV422,
643};
644
Thierry Redingc7679302014-10-21 13:51:53 +0200645static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
646 struct tegra_dc *dc,
647 unsigned int index)
648{
649 struct tegra_plane *plane;
650 unsigned int num_formats;
651 const u32 *formats;
652 int err;
653
654 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
655 if (!plane)
656 return ERR_PTR(-ENOMEM);
657
Thierry Redingc4755fb2017-11-13 11:08:13 +0100658 /* XXX compute offset so that we can directly access windows */
659 plane->offset = 0;
Thierry Redingc7679302014-10-21 13:51:53 +0200660 plane->index = index;
Thierry Redingc4755fb2017-11-13 11:08:13 +0100661 plane->depth = 0;
Thierry Redingc7679302014-10-21 13:51:53 +0200662
663 num_formats = ARRAY_SIZE(tegra_overlay_plane_formats);
664 formats = tegra_overlay_plane_formats;
665
666 err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe,
Thierry Reding301e0dd2017-08-30 18:04:12 +0200667 &tegra_plane_funcs, formats,
Ben Widawskye6fc3b62017-07-23 20:46:38 -0700668 num_formats, NULL,
669 DRM_PLANE_TYPE_OVERLAY, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +0200670 if (err < 0) {
671 kfree(plane);
672 return ERR_PTR(err);
673 }
674
Thierry Redinga4bfa092017-08-30 17:34:10 +0200675 drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
Thierry Reding4aa3df72014-11-24 16:27:13 +0100676
Thierry Redingc7679302014-10-21 13:51:53 +0200677 return &plane->base;
678}
679
Thierry Reding47307952017-08-30 17:42:54 +0200680static struct drm_plane *tegra_dc_add_shared_planes(struct drm_device *drm,
681 struct tegra_dc *dc)
Thierry Redingf34bc782012-11-04 21:47:13 +0100682{
Thierry Reding47307952017-08-30 17:42:54 +0200683 struct drm_plane *plane, *primary = NULL;
684 unsigned int i, j;
685
686 for (i = 0; i < dc->soc->num_wgrps; i++) {
687 const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];
688
689 if (wgrp->dc == dc->pipe) {
690 for (j = 0; j < wgrp->num_windows; j++) {
691 unsigned int index = wgrp->windows[j];
692
693 plane = tegra_shared_plane_create(drm, dc,
694 wgrp->index,
695 index);
696 if (IS_ERR(plane))
697 return plane;
698
699 /*
700 * Choose the first shared plane owned by this
701 * head as the primary plane.
702 */
703 if (!primary) {
704 plane->type = DRM_PLANE_TYPE_PRIMARY;
705 primary = plane;
706 }
707 }
708 }
709 }
710
711 return primary;
712}
713
714static struct drm_plane *tegra_dc_add_planes(struct drm_device *drm,
715 struct tegra_dc *dc)
716{
717 struct drm_plane *plane, *primary;
Thierry Redingf34bc782012-11-04 21:47:13 +0100718 unsigned int i;
Thierry Redingf34bc782012-11-04 21:47:13 +0100719
Thierry Reding47307952017-08-30 17:42:54 +0200720 primary = tegra_primary_plane_create(drm, dc);
721 if (IS_ERR(primary))
722 return primary;
723
Thierry Redingf34bc782012-11-04 21:47:13 +0100724 for (i = 0; i < 2; i++) {
Thierry Redingc7679302014-10-21 13:51:53 +0200725 plane = tegra_dc_overlay_plane_create(drm, dc, 1 + i);
Thierry Reding47307952017-08-30 17:42:54 +0200726 if (IS_ERR(plane)) {
727 /* XXX tegra_plane_destroy() */
728 drm_plane_cleanup(primary);
729 kfree(primary);
730 return plane;
731 }
Thierry Redingf34bc782012-11-04 21:47:13 +0100732 }
733
Thierry Reding47307952017-08-30 17:42:54 +0200734 return primary;
Thierry Redingf34bc782012-11-04 21:47:13 +0100735}
736
Thierry Redingf002abc2013-10-14 14:06:02 +0200737static void tegra_dc_destroy(struct drm_crtc *crtc)
738{
739 drm_crtc_cleanup(crtc);
Thierry Redingf002abc2013-10-14 14:06:02 +0200740}
741
Thierry Redingca915b12014-12-08 16:14:45 +0100742static void tegra_crtc_reset(struct drm_crtc *crtc)
743{
744 struct tegra_dc_state *state;
745
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100746 if (crtc->state)
Daniel Vetterec2dc6a2016-05-09 16:34:09 +0200747 __drm_atomic_helper_crtc_destroy_state(crtc->state);
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100748
Thierry Redingca915b12014-12-08 16:14:45 +0100749 kfree(crtc->state);
750 crtc->state = NULL;
751
752 state = kzalloc(sizeof(*state), GFP_KERNEL);
Thierry Reding332bbe72015-01-28 15:03:31 +0100753 if (state) {
Thierry Redingca915b12014-12-08 16:14:45 +0100754 crtc->state = &state->base;
Thierry Reding332bbe72015-01-28 15:03:31 +0100755 crtc->state->crtc = crtc;
756 }
Thierry Reding31930d42015-07-02 17:04:06 +0200757
758 drm_crtc_vblank_reset(crtc);
Thierry Redingca915b12014-12-08 16:14:45 +0100759}
760
761static struct drm_crtc_state *
762tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
763{
764 struct tegra_dc_state *state = to_dc_state(crtc->state);
765 struct tegra_dc_state *copy;
766
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100767 copy = kmalloc(sizeof(*copy), GFP_KERNEL);
Thierry Redingca915b12014-12-08 16:14:45 +0100768 if (!copy)
769 return NULL;
770
Thierry Reding3b59b7ac2015-01-28 15:01:22 +0100771 __drm_atomic_helper_crtc_duplicate_state(crtc, &copy->base);
772 copy->clk = state->clk;
773 copy->pclk = state->pclk;
774 copy->div = state->div;
775 copy->planes = state->planes;
Thierry Redingca915b12014-12-08 16:14:45 +0100776
777 return &copy->base;
778}
779
780static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
781 struct drm_crtc_state *state)
782{
Daniel Vetterec2dc6a2016-05-09 16:34:09 +0200783 __drm_atomic_helper_crtc_destroy_state(state);
Thierry Redingca915b12014-12-08 16:14:45 +0100784 kfree(state);
785}
786
Thierry Redingb95800e2017-11-08 13:40:54 +0100787#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
788
789static const struct debugfs_reg32 tegra_dc_regs[] = {
790 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT),
791 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL),
792 DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_ERROR),
793 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT),
794 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL),
795 DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_ERROR),
796 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT),
797 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL),
798 DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_ERROR),
799 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT),
800 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL),
801 DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_ERROR),
802 DEBUGFS_REG32(DC_CMD_CONT_SYNCPT_VSYNC),
803 DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND_OPTION0),
804 DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND),
805 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE),
806 DEBUGFS_REG32(DC_CMD_DISPLAY_POWER_CONTROL),
807 DEBUGFS_REG32(DC_CMD_INT_STATUS),
808 DEBUGFS_REG32(DC_CMD_INT_MASK),
809 DEBUGFS_REG32(DC_CMD_INT_ENABLE),
810 DEBUGFS_REG32(DC_CMD_INT_TYPE),
811 DEBUGFS_REG32(DC_CMD_INT_POLARITY),
812 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE1),
813 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE2),
814 DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE3),
815 DEBUGFS_REG32(DC_CMD_STATE_ACCESS),
816 DEBUGFS_REG32(DC_CMD_STATE_CONTROL),
817 DEBUGFS_REG32(DC_CMD_DISPLAY_WINDOW_HEADER),
818 DEBUGFS_REG32(DC_CMD_REG_ACT_CONTROL),
819 DEBUGFS_REG32(DC_COM_CRC_CONTROL),
820 DEBUGFS_REG32(DC_COM_CRC_CHECKSUM),
821 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(0)),
822 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(1)),
823 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(2)),
824 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(3)),
825 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(0)),
826 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(1)),
827 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(2)),
828 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(3)),
829 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(0)),
830 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(1)),
831 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(2)),
832 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(3)),
833 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(0)),
834 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(1)),
835 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(2)),
836 DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(3)),
837 DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(0)),
838 DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(1)),
839 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(0)),
840 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(1)),
841 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(2)),
842 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(3)),
843 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(4)),
844 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(5)),
845 DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(6)),
846 DEBUGFS_REG32(DC_COM_PIN_MISC_CONTROL),
847 DEBUGFS_REG32(DC_COM_PIN_PM0_CONTROL),
848 DEBUGFS_REG32(DC_COM_PIN_PM0_DUTY_CYCLE),
849 DEBUGFS_REG32(DC_COM_PIN_PM1_CONTROL),
850 DEBUGFS_REG32(DC_COM_PIN_PM1_DUTY_CYCLE),
851 DEBUGFS_REG32(DC_COM_SPI_CONTROL),
852 DEBUGFS_REG32(DC_COM_SPI_START_BYTE),
853 DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_AB),
854 DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_CD),
855 DEBUGFS_REG32(DC_COM_HSPI_CS_DC),
856 DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_A),
857 DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_B),
858 DEBUGFS_REG32(DC_COM_GPIO_CTRL),
859 DEBUGFS_REG32(DC_COM_GPIO_DEBOUNCE_COUNTER),
860 DEBUGFS_REG32(DC_COM_CRC_CHECKSUM_LATCHED),
861 DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS0),
862 DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS1),
863 DEBUGFS_REG32(DC_DISP_DISP_WIN_OPTIONS),
864 DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY),
865 DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER),
866 DEBUGFS_REG32(DC_DISP_DISP_TIMING_OPTIONS),
867 DEBUGFS_REG32(DC_DISP_REF_TO_SYNC),
868 DEBUGFS_REG32(DC_DISP_SYNC_WIDTH),
869 DEBUGFS_REG32(DC_DISP_BACK_PORCH),
870 DEBUGFS_REG32(DC_DISP_ACTIVE),
871 DEBUGFS_REG32(DC_DISP_FRONT_PORCH),
872 DEBUGFS_REG32(DC_DISP_H_PULSE0_CONTROL),
873 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_A),
874 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_B),
875 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_C),
876 DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_D),
877 DEBUGFS_REG32(DC_DISP_H_PULSE1_CONTROL),
878 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_A),
879 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_B),
880 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_C),
881 DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_D),
882 DEBUGFS_REG32(DC_DISP_H_PULSE2_CONTROL),
883 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_A),
884 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_B),
885 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_C),
886 DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_D),
887 DEBUGFS_REG32(DC_DISP_V_PULSE0_CONTROL),
888 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_A),
889 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_B),
890 DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_C),
891 DEBUGFS_REG32(DC_DISP_V_PULSE1_CONTROL),
892 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_A),
893 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_B),
894 DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_C),
895 DEBUGFS_REG32(DC_DISP_V_PULSE2_CONTROL),
896 DEBUGFS_REG32(DC_DISP_V_PULSE2_POSITION_A),
897 DEBUGFS_REG32(DC_DISP_V_PULSE3_CONTROL),
898 DEBUGFS_REG32(DC_DISP_V_PULSE3_POSITION_A),
899 DEBUGFS_REG32(DC_DISP_M0_CONTROL),
900 DEBUGFS_REG32(DC_DISP_M1_CONTROL),
901 DEBUGFS_REG32(DC_DISP_DI_CONTROL),
902 DEBUGFS_REG32(DC_DISP_PP_CONTROL),
903 DEBUGFS_REG32(DC_DISP_PP_SELECT_A),
904 DEBUGFS_REG32(DC_DISP_PP_SELECT_B),
905 DEBUGFS_REG32(DC_DISP_PP_SELECT_C),
906 DEBUGFS_REG32(DC_DISP_PP_SELECT_D),
907 DEBUGFS_REG32(DC_DISP_DISP_CLOCK_CONTROL),
908 DEBUGFS_REG32(DC_DISP_DISP_INTERFACE_CONTROL),
909 DEBUGFS_REG32(DC_DISP_DISP_COLOR_CONTROL),
910 DEBUGFS_REG32(DC_DISP_SHIFT_CLOCK_OPTIONS),
911 DEBUGFS_REG32(DC_DISP_DATA_ENABLE_OPTIONS),
912 DEBUGFS_REG32(DC_DISP_SERIAL_INTERFACE_OPTIONS),
913 DEBUGFS_REG32(DC_DISP_LCD_SPI_OPTIONS),
914 DEBUGFS_REG32(DC_DISP_BORDER_COLOR),
915 DEBUGFS_REG32(DC_DISP_COLOR_KEY0_LOWER),
916 DEBUGFS_REG32(DC_DISP_COLOR_KEY0_UPPER),
917 DEBUGFS_REG32(DC_DISP_COLOR_KEY1_LOWER),
918 DEBUGFS_REG32(DC_DISP_COLOR_KEY1_UPPER),
919 DEBUGFS_REG32(DC_DISP_CURSOR_FOREGROUND),
920 DEBUGFS_REG32(DC_DISP_CURSOR_BACKGROUND),
921 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR),
922 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_NS),
923 DEBUGFS_REG32(DC_DISP_CURSOR_POSITION),
924 DEBUGFS_REG32(DC_DISP_CURSOR_POSITION_NS),
925 DEBUGFS_REG32(DC_DISP_INIT_SEQ_CONTROL),
926 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_A),
927 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_B),
928 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_C),
929 DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_D),
930 DEBUGFS_REG32(DC_DISP_DC_MCCIF_FIFOCTRL),
931 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0A_HYST),
932 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0B_HYST),
933 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1A_HYST),
934 DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1B_HYST),
935 DEBUGFS_REG32(DC_DISP_DAC_CRT_CTRL),
936 DEBUGFS_REG32(DC_DISP_DISP_MISC_CONTROL),
937 DEBUGFS_REG32(DC_DISP_SD_CONTROL),
938 DEBUGFS_REG32(DC_DISP_SD_CSC_COEFF),
939 DEBUGFS_REG32(DC_DISP_SD_LUT(0)),
940 DEBUGFS_REG32(DC_DISP_SD_LUT(1)),
941 DEBUGFS_REG32(DC_DISP_SD_LUT(2)),
942 DEBUGFS_REG32(DC_DISP_SD_LUT(3)),
943 DEBUGFS_REG32(DC_DISP_SD_LUT(4)),
944 DEBUGFS_REG32(DC_DISP_SD_LUT(5)),
945 DEBUGFS_REG32(DC_DISP_SD_LUT(6)),
946 DEBUGFS_REG32(DC_DISP_SD_LUT(7)),
947 DEBUGFS_REG32(DC_DISP_SD_LUT(8)),
948 DEBUGFS_REG32(DC_DISP_SD_FLICKER_CONTROL),
949 DEBUGFS_REG32(DC_DISP_DC_PIXEL_COUNT),
950 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(0)),
951 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(1)),
952 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(2)),
953 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(3)),
954 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(4)),
955 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(5)),
956 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(6)),
957 DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(7)),
958 DEBUGFS_REG32(DC_DISP_SD_BL_TF(0)),
959 DEBUGFS_REG32(DC_DISP_SD_BL_TF(1)),
960 DEBUGFS_REG32(DC_DISP_SD_BL_TF(2)),
961 DEBUGFS_REG32(DC_DISP_SD_BL_TF(3)),
962 DEBUGFS_REG32(DC_DISP_SD_BL_CONTROL),
963 DEBUGFS_REG32(DC_DISP_SD_HW_K_VALUES),
964 DEBUGFS_REG32(DC_DISP_SD_MAN_K_VALUES),
965 DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_HI),
966 DEBUGFS_REG32(DC_DISP_BLEND_CURSOR_CONTROL),
967 DEBUGFS_REG32(DC_WIN_WIN_OPTIONS),
968 DEBUGFS_REG32(DC_WIN_BYTE_SWAP),
969 DEBUGFS_REG32(DC_WIN_BUFFER_CONTROL),
970 DEBUGFS_REG32(DC_WIN_COLOR_DEPTH),
971 DEBUGFS_REG32(DC_WIN_POSITION),
972 DEBUGFS_REG32(DC_WIN_SIZE),
973 DEBUGFS_REG32(DC_WIN_PRESCALED_SIZE),
974 DEBUGFS_REG32(DC_WIN_H_INITIAL_DDA),
975 DEBUGFS_REG32(DC_WIN_V_INITIAL_DDA),
976 DEBUGFS_REG32(DC_WIN_DDA_INC),
977 DEBUGFS_REG32(DC_WIN_LINE_STRIDE),
978 DEBUGFS_REG32(DC_WIN_BUF_STRIDE),
979 DEBUGFS_REG32(DC_WIN_UV_BUF_STRIDE),
980 DEBUGFS_REG32(DC_WIN_BUFFER_ADDR_MODE),
981 DEBUGFS_REG32(DC_WIN_DV_CONTROL),
982 DEBUGFS_REG32(DC_WIN_BLEND_NOKEY),
983 DEBUGFS_REG32(DC_WIN_BLEND_1WIN),
984 DEBUGFS_REG32(DC_WIN_BLEND_2WIN_X),
985 DEBUGFS_REG32(DC_WIN_BLEND_2WIN_Y),
986 DEBUGFS_REG32(DC_WIN_BLEND_3WIN_XY),
987 DEBUGFS_REG32(DC_WIN_HP_FETCH_CONTROL),
988 DEBUGFS_REG32(DC_WINBUF_START_ADDR),
989 DEBUGFS_REG32(DC_WINBUF_START_ADDR_NS),
990 DEBUGFS_REG32(DC_WINBUF_START_ADDR_U),
991 DEBUGFS_REG32(DC_WINBUF_START_ADDR_U_NS),
992 DEBUGFS_REG32(DC_WINBUF_START_ADDR_V),
993 DEBUGFS_REG32(DC_WINBUF_START_ADDR_V_NS),
994 DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET),
995 DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET_NS),
996 DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET),
997 DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET_NS),
998 DEBUGFS_REG32(DC_WINBUF_UFLOW_STATUS),
999 DEBUGFS_REG32(DC_WINBUF_AD_UFLOW_STATUS),
1000 DEBUGFS_REG32(DC_WINBUF_BD_UFLOW_STATUS),
1001 DEBUGFS_REG32(DC_WINBUF_CD_UFLOW_STATUS),
1002};
1003
1004static int tegra_dc_show_regs(struct seq_file *s, void *data)
1005{
1006 struct drm_info_node *node = s->private;
1007 struct tegra_dc *dc = node->info_ent->data;
1008 unsigned int i;
1009 int err = 0;
1010
1011 drm_modeset_lock(&dc->base.mutex, NULL);
1012
1013 if (!dc->base.state->active) {
1014 err = -EBUSY;
1015 goto unlock;
1016 }
1017
1018 for (i = 0; i < ARRAY_SIZE(tegra_dc_regs); i++) {
1019 unsigned int offset = tegra_dc_regs[i].offset;
1020
1021 seq_printf(s, "%-40s %#05x %08x\n", tegra_dc_regs[i].name,
1022 offset, tegra_dc_readl(dc, offset));
1023 }
1024
1025unlock:
1026 drm_modeset_unlock(&dc->base.mutex);
1027 return err;
1028}
1029
1030static int tegra_dc_show_crc(struct seq_file *s, void *data)
1031{
1032 struct drm_info_node *node = s->private;
1033 struct tegra_dc *dc = node->info_ent->data;
1034 int err = 0;
1035 u32 value;
1036
1037 drm_modeset_lock(&dc->base.mutex, NULL);
1038
1039 if (!dc->base.state->active) {
1040 err = -EBUSY;
1041 goto unlock;
1042 }
1043
1044 value = DC_COM_CRC_CONTROL_ACTIVE_DATA | DC_COM_CRC_CONTROL_ENABLE;
1045 tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL);
1046 tegra_dc_commit(dc);
1047
1048 drm_crtc_wait_one_vblank(&dc->base);
1049 drm_crtc_wait_one_vblank(&dc->base);
1050
1051 value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM);
1052 seq_printf(s, "%08x\n", value);
1053
1054 tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
1055
1056unlock:
1057 drm_modeset_unlock(&dc->base.mutex);
1058 return err;
1059}
1060
1061static int tegra_dc_show_stats(struct seq_file *s, void *data)
1062{
1063 struct drm_info_node *node = s->private;
1064 struct tegra_dc *dc = node->info_ent->data;
1065
1066 seq_printf(s, "frames: %lu\n", dc->stats.frames);
1067 seq_printf(s, "vblank: %lu\n", dc->stats.vblank);
1068 seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
1069 seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
1070
1071 return 0;
1072}
1073
1074static struct drm_info_list debugfs_files[] = {
1075 { "regs", tegra_dc_show_regs, 0, NULL },
1076 { "crc", tegra_dc_show_crc, 0, NULL },
1077 { "stats", tegra_dc_show_stats, 0, NULL },
1078};
1079
1080static int tegra_dc_late_register(struct drm_crtc *crtc)
1081{
1082 unsigned int i, count = ARRAY_SIZE(debugfs_files);
1083 struct drm_minor *minor = crtc->dev->primary;
1084 struct dentry *root = crtc->debugfs_entry;
1085 struct tegra_dc *dc = to_tegra_dc(crtc);
1086 int err;
1087
1088 dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1089 GFP_KERNEL);
1090 if (!dc->debugfs_files)
1091 return -ENOMEM;
1092
1093 for (i = 0; i < count; i++)
1094 dc->debugfs_files[i].data = dc;
1095
1096 err = drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
1097 if (err < 0)
1098 goto free;
1099
1100 return 0;
1101
1102free:
1103 kfree(dc->debugfs_files);
1104 dc->debugfs_files = NULL;
1105
1106 return err;
1107}
1108
1109static void tegra_dc_early_unregister(struct drm_crtc *crtc)
1110{
1111 unsigned int count = ARRAY_SIZE(debugfs_files);
1112 struct drm_minor *minor = crtc->dev->primary;
1113 struct tegra_dc *dc = to_tegra_dc(crtc);
1114
1115 drm_debugfs_remove_files(dc->debugfs_files, count, minor);
1116 kfree(dc->debugfs_files);
1117 dc->debugfs_files = NULL;
1118}
1119
Thierry Redingc49c81e2017-11-08 13:32:05 +01001120static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc)
1121{
1122 struct tegra_dc *dc = to_tegra_dc(crtc);
1123
Thierry Reding47307952017-08-30 17:42:54 +02001124 /* XXX vblank syncpoints don't work with nvdisplay yet */
1125 if (dc->syncpt && !dc->soc->has_nvdisplay)
Thierry Redingc49c81e2017-11-08 13:32:05 +01001126 return host1x_syncpt_read(dc->syncpt);
1127
1128 /* fallback to software emulated VBLANK counter */
1129 return drm_crtc_vblank_count(&dc->base);
1130}
1131
1132static int tegra_dc_enable_vblank(struct drm_crtc *crtc)
1133{
1134 struct tegra_dc *dc = to_tegra_dc(crtc);
1135 unsigned long value, flags;
1136
1137 spin_lock_irqsave(&dc->lock, flags);
1138
1139 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1140 value |= VBLANK_INT;
1141 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1142
1143 spin_unlock_irqrestore(&dc->lock, flags);
1144
1145 return 0;
1146}
1147
1148static void tegra_dc_disable_vblank(struct drm_crtc *crtc)
1149{
1150 struct tegra_dc *dc = to_tegra_dc(crtc);
1151 unsigned long value, flags;
1152
1153 spin_lock_irqsave(&dc->lock, flags);
1154
1155 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1156 value &= ~VBLANK_INT;
1157 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1158
1159 spin_unlock_irqrestore(&dc->lock, flags);
1160}
1161
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001162static const struct drm_crtc_funcs tegra_crtc_funcs = {
Thierry Reding1503ca42014-11-24 17:41:23 +01001163 .page_flip = drm_atomic_helper_page_flip,
Thierry Reding74f48792014-11-24 17:08:20 +01001164 .set_config = drm_atomic_helper_set_config,
Thierry Redingf002abc2013-10-14 14:06:02 +02001165 .destroy = tegra_dc_destroy,
Thierry Redingca915b12014-12-08 16:14:45 +01001166 .reset = tegra_crtc_reset,
1167 .atomic_duplicate_state = tegra_crtc_atomic_duplicate_state,
1168 .atomic_destroy_state = tegra_crtc_atomic_destroy_state,
Thierry Redingb95800e2017-11-08 13:40:54 +01001169 .late_register = tegra_dc_late_register,
1170 .early_unregister = tegra_dc_early_unregister,
Shawn Guo10437d92017-02-07 17:16:32 +08001171 .get_vblank_counter = tegra_dc_get_vblank_counter,
1172 .enable_vblank = tegra_dc_enable_vblank,
1173 .disable_vblank = tegra_dc_disable_vblank,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001174};
1175
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001176static int tegra_dc_set_timings(struct tegra_dc *dc,
1177 struct drm_display_mode *mode)
1178{
Thierry Reding0444c0f2014-04-16 09:22:38 +02001179 unsigned int h_ref_to_sync = 1;
1180 unsigned int v_ref_to_sync = 1;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001181 unsigned long value;
1182
Thierry Reding47307952017-08-30 17:42:54 +02001183 if (!dc->soc->has_nvdisplay) {
1184 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001185
Thierry Reding47307952017-08-30 17:42:54 +02001186 value = (v_ref_to_sync << 16) | h_ref_to_sync;
1187 tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
1188 }
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001189
1190 value = ((mode->vsync_end - mode->vsync_start) << 16) |
1191 ((mode->hsync_end - mode->hsync_start) << 0);
1192 tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
1193
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001194 value = ((mode->vtotal - mode->vsync_end) << 16) |
1195 ((mode->htotal - mode->hsync_end) << 0);
Lucas Stach40495082012-12-19 21:38:52 +00001196 tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
1197
1198 value = ((mode->vsync_start - mode->vdisplay) << 16) |
1199 ((mode->hsync_start - mode->hdisplay) << 0);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001200 tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
1201
1202 value = (mode->vdisplay << 16) | mode->hdisplay;
1203 tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
1204
1205 return 0;
1206}
1207
Thierry Reding9d910b62015-01-28 15:25:54 +01001208/**
1209 * tegra_dc_state_setup_clock - check clock settings and store them in atomic
1210 * state
1211 * @dc: display controller
1212 * @crtc_state: CRTC atomic state
1213 * @clk: parent clock for display controller
1214 * @pclk: pixel clock
1215 * @div: shift clock divider
1216 *
1217 * Returns:
1218 * 0 on success or a negative error-code on failure.
1219 */
Thierry Redingca915b12014-12-08 16:14:45 +01001220int tegra_dc_state_setup_clock(struct tegra_dc *dc,
1221 struct drm_crtc_state *crtc_state,
1222 struct clk *clk, unsigned long pclk,
1223 unsigned int div)
1224{
1225 struct tegra_dc_state *state = to_dc_state(crtc_state);
1226
Thierry Redingd2982742015-01-22 08:48:25 +01001227 if (!clk_has_parent(dc->clk, clk))
1228 return -EINVAL;
1229
Thierry Redingca915b12014-12-08 16:14:45 +01001230 state->clk = clk;
1231 state->pclk = pclk;
1232 state->div = div;
1233
1234 return 0;
1235}
1236
Thierry Reding76d59ed2014-12-19 15:09:16 +01001237static void tegra_dc_commit_state(struct tegra_dc *dc,
1238 struct tegra_dc_state *state)
1239{
1240 u32 value;
1241 int err;
1242
1243 err = clk_set_parent(dc->clk, state->clk);
1244 if (err < 0)
1245 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
1246
1247 /*
1248 * Outputs may not want to change the parent clock rate. This is only
1249 * relevant to Tegra20 where only a single display PLL is available.
1250 * Since that PLL would typically be used for HDMI, an internal LVDS
1251 * panel would need to be driven by some other clock such as PLL_P
1252 * which is shared with other peripherals. Changing the clock rate
1253 * should therefore be avoided.
1254 */
1255 if (state->pclk > 0) {
1256 err = clk_set_rate(state->clk, state->pclk);
1257 if (err < 0)
1258 dev_err(dc->dev,
1259 "failed to set clock rate to %lu Hz\n",
1260 state->pclk);
1261 }
1262
1263 DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),
1264 state->div);
1265 DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);
1266
Thierry Reding47307952017-08-30 17:42:54 +02001267 if (!dc->soc->has_nvdisplay) {
1268 value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1;
1269 tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
1270 }
Thierry Reding39e08af2017-08-30 17:38:39 +02001271
1272 err = clk_set_rate(dc->clk, state->pclk);
1273 if (err < 0)
1274 dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
1275 dc->clk, state->pclk, err);
Thierry Reding76d59ed2014-12-19 15:09:16 +01001276}
1277
Thierry Reding003fc842015-08-03 13:16:26 +02001278static void tegra_dc_stop(struct tegra_dc *dc)
1279{
1280 u32 value;
1281
1282 /* stop the display controller */
1283 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
1284 value &= ~DISP_CTRL_MODE_MASK;
1285 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
1286
1287 tegra_dc_commit(dc);
1288}
1289
1290static bool tegra_dc_idle(struct tegra_dc *dc)
1291{
1292 u32 value;
1293
1294 value = tegra_dc_readl_active(dc, DC_CMD_DISPLAY_COMMAND);
1295
1296 return (value & DISP_CTRL_MODE_MASK) == 0;
1297}
1298
1299static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout)
1300{
1301 timeout = jiffies + msecs_to_jiffies(timeout);
1302
1303 while (time_before(jiffies, timeout)) {
1304 if (tegra_dc_idle(dc))
1305 return 0;
1306
1307 usleep_range(1000, 2000);
1308 }
1309
1310 dev_dbg(dc->dev, "timeout waiting for DC to become idle\n");
1311 return -ETIMEDOUT;
1312}
1313
Laurent Pinchart64581712017-06-30 12:36:45 +03001314static void tegra_crtc_atomic_disable(struct drm_crtc *crtc,
1315 struct drm_crtc_state *old_state)
Thierry Reding003fc842015-08-03 13:16:26 +02001316{
1317 struct tegra_dc *dc = to_tegra_dc(crtc);
1318 u32 value;
1319
1320 if (!tegra_dc_idle(dc)) {
1321 tegra_dc_stop(dc);
1322
1323 /*
1324 * Ignore the return value, there isn't anything useful to do
1325 * in case this fails.
1326 */
1327 tegra_dc_wait_idle(dc, 100);
1328 }
1329
1330 /*
1331 * This should really be part of the RGB encoder driver, but clearing
1332 * these bits has the side-effect of stopping the display controller.
1333 * When that happens no VBLANK interrupts will be raised. At the same
1334 * time the encoder is disabled before the display controller, so the
1335 * above code is always going to timeout waiting for the controller
1336 * to go idle.
1337 *
1338 * Given the close coupling between the RGB encoder and the display
1339 * controller doing it here is still kind of okay. None of the other
1340 * encoder drivers require these bits to be cleared.
1341 *
1342 * XXX: Perhaps given that the display controller is switched off at
1343 * this point anyway maybe clearing these bits isn't even useful for
1344 * the RGB encoder?
1345 */
1346 if (dc->rgb) {
1347 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
1348 value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
1349 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
1350 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
1351 }
1352
1353 tegra_dc_stats_reset(&dc->stats);
1354 drm_crtc_vblank_off(crtc);
Thierry Reding33a8eb82015-08-03 13:20:49 +02001355
Thierry Reding9d99ab62017-10-12 17:40:46 +02001356 spin_lock_irq(&crtc->dev->event_lock);
1357
1358 if (crtc->state->event) {
1359 drm_crtc_send_vblank_event(crtc, crtc->state->event);
1360 crtc->state->event = NULL;
1361 }
1362
1363 spin_unlock_irq(&crtc->dev->event_lock);
1364
Thierry Reding33a8eb82015-08-03 13:20:49 +02001365 pm_runtime_put_sync(dc->dev);
Thierry Reding003fc842015-08-03 13:16:26 +02001366}
1367
Laurent Pinchart0b20a0f2017-06-30 12:36:44 +03001368static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
1369 struct drm_crtc_state *old_state)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001370{
Thierry Reding4aa3df72014-11-24 16:27:13 +01001371 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
Thierry Reding76d59ed2014-12-19 15:09:16 +01001372 struct tegra_dc_state *state = to_dc_state(crtc->state);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001373 struct tegra_dc *dc = to_tegra_dc(crtc);
Thierry Redingdbb3f2f2014-03-26 12:32:14 +01001374 u32 value;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001375
Thierry Reding33a8eb82015-08-03 13:20:49 +02001376 pm_runtime_get_sync(dc->dev);
1377
1378 /* initialize display controller */
1379 if (dc->syncpt) {
Thierry Reding47307952017-08-30 17:42:54 +02001380 u32 syncpt = host1x_syncpt_id(dc->syncpt), enable;
1381
1382 if (dc->soc->has_nvdisplay)
1383 enable = 1 << 31;
1384 else
1385 enable = 1 << 8;
Thierry Reding33a8eb82015-08-03 13:20:49 +02001386
1387 value = SYNCPT_CNTRL_NO_STALL;
1388 tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
1389
Thierry Reding47307952017-08-30 17:42:54 +02001390 value = enable | syncpt;
Thierry Reding33a8eb82015-08-03 13:20:49 +02001391 tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
1392 }
1393
Thierry Reding47307952017-08-30 17:42:54 +02001394 if (dc->soc->has_nvdisplay) {
1395 value = DSC_TO_UF_INT | DSC_BBUF_UF_INT | DSC_RBUF_UF_INT |
1396 DSC_OBUF_UF_INT;
1397 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
Thierry Reding33a8eb82015-08-03 13:20:49 +02001398
Thierry Reding47307952017-08-30 17:42:54 +02001399 value = DSC_TO_UF_INT | DSC_BBUF_UF_INT | DSC_RBUF_UF_INT |
1400 DSC_OBUF_UF_INT | SD3_BUCKET_WALK_DONE_INT |
1401 HEAD_UF_INT | MSF_INT | REG_TMOUT_INT |
1402 REGION_CRC_INT | V_PULSE2_INT | V_PULSE3_INT |
1403 VBLANK_INT | FRAME_END_INT;
1404 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
Thierry Reding33a8eb82015-08-03 13:20:49 +02001405
Thierry Reding47307952017-08-30 17:42:54 +02001406 value = SD3_BUCKET_WALK_DONE_INT | HEAD_UF_INT | VBLANK_INT |
1407 FRAME_END_INT;
1408 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
Thierry Reding33a8eb82015-08-03 13:20:49 +02001409
Thierry Reding47307952017-08-30 17:42:54 +02001410 value = HEAD_UF_INT | REG_TMOUT_INT | FRAME_END_INT;
1411 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
Thierry Reding33a8eb82015-08-03 13:20:49 +02001412
Thierry Reding47307952017-08-30 17:42:54 +02001413 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
1414 } else {
1415 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1416 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1417 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
Thierry Reding33a8eb82015-08-03 13:20:49 +02001418
Thierry Reding47307952017-08-30 17:42:54 +02001419 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1420 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1421 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
1422
1423 /* initialize timer */
1424 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
1425 WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
1426 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
1427
1428 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
1429 WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
1430 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
1431
1432 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1433 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1434 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
1435
1436 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1437 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1438 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1439 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02001440
Thierry Reding7116e9a2017-11-13 11:20:48 +01001441 if (dc->soc->supports_background_color)
1442 tegra_dc_writel(dc, 0, DC_DISP_BLEND_BACKGROUND_COLOR);
1443 else
Thierry Reding33a8eb82015-08-03 13:20:49 +02001444 tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);
1445
1446 /* apply PLL and pixel clock changes */
Thierry Reding76d59ed2014-12-19 15:09:16 +01001447 tegra_dc_commit_state(dc, state);
1448
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001449 /* program display mode */
1450 tegra_dc_set_timings(dc, mode);
1451
Thierry Reding8620fc62013-12-12 11:03:59 +01001452 /* interlacing isn't supported yet, so disable it */
1453 if (dc->soc->supports_interlacing) {
1454 value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
1455 value &= ~INTERLACE_ENABLE;
1456 tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
1457 }
Thierry Reding666cb872014-12-08 16:32:47 +01001458
1459 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
1460 value &= ~DISP_CTRL_MODE_MASK;
1461 value |= DISP_CTRL_MODE_C_DISPLAY;
1462 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
1463
Thierry Reding47307952017-08-30 17:42:54 +02001464 if (!dc->soc->has_nvdisplay) {
1465 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
1466 value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
1467 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
1468 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
1469 }
1470
1471 /* enable underflow reporting and display red for missing pixels */
1472 if (dc->soc->has_nvdisplay) {
1473 value = UNDERFLOW_MODE_RED | UNDERFLOW_REPORT_ENABLE;
1474 tegra_dc_writel(dc, value, DC_COM_RG_UNDERFLOW);
1475 }
Thierry Reding666cb872014-12-08 16:32:47 +01001476
1477 tegra_dc_commit(dc);
Thierry Reding23fb4742012-11-28 11:38:24 +01001478
Thierry Reding8ff64c12014-10-08 14:48:51 +02001479 drm_crtc_vblank_on(crtc);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001480}
1481
Thierry Reding4aa3df72014-11-24 16:27:13 +01001482static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
1483 struct drm_crtc_state *state)
1484{
Thierry Redingc4755fb2017-11-13 11:08:13 +01001485 struct tegra_atomic_state *s = to_tegra_atomic_state(state->state);
1486 struct tegra_dc_state *tegra = to_dc_state(state);
1487
1488 /*
1489 * The display hub display clock needs to be fed by the display clock
1490 * with the highest frequency to ensure proper functioning of all the
1491 * displays.
1492 *
1493 * Note that this isn't used before Tegra186, but it doesn't hurt and
1494 * conditionalizing it would make the code less clean.
1495 */
1496 if (state->active) {
1497 if (!s->clk_disp || tegra->pclk > s->rate) {
1498 s->dc = to_tegra_dc(crtc);
1499 s->clk_disp = s->dc->clk;
1500 s->rate = tegra->pclk;
1501 }
1502 }
1503
Thierry Reding4aa3df72014-11-24 16:27:13 +01001504 return 0;
1505}
1506
Maarten Lankhorst613d2b22015-07-21 13:28:58 +02001507static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
1508 struct drm_crtc_state *old_crtc_state)
Thierry Reding4aa3df72014-11-24 16:27:13 +01001509{
Thierry Reding9d99ab62017-10-12 17:40:46 +02001510 unsigned long flags;
Thierry Reding1503ca42014-11-24 17:41:23 +01001511
1512 if (crtc->state->event) {
Thierry Reding9d99ab62017-10-12 17:40:46 +02001513 spin_lock_irqsave(&crtc->dev->event_lock, flags);
Thierry Reding1503ca42014-11-24 17:41:23 +01001514
Thierry Reding9d99ab62017-10-12 17:40:46 +02001515 if (drm_crtc_vblank_get(crtc) != 0)
1516 drm_crtc_send_vblank_event(crtc, crtc->state->event);
1517 else
1518 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
Thierry Reding1503ca42014-11-24 17:41:23 +01001519
Thierry Reding9d99ab62017-10-12 17:40:46 +02001520 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
1521
Thierry Reding1503ca42014-11-24 17:41:23 +01001522 crtc->state->event = NULL;
1523 }
Thierry Reding4aa3df72014-11-24 16:27:13 +01001524}
1525
Maarten Lankhorst613d2b22015-07-21 13:28:58 +02001526static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
1527 struct drm_crtc_state *old_crtc_state)
Thierry Reding4aa3df72014-11-24 16:27:13 +01001528{
Thierry Reding47802b02014-11-26 12:28:39 +01001529 struct tegra_dc_state *state = to_dc_state(crtc->state);
1530 struct tegra_dc *dc = to_tegra_dc(crtc);
Thierry Reding47307952017-08-30 17:42:54 +02001531 u32 value;
Thierry Reding47802b02014-11-26 12:28:39 +01001532
Thierry Reding47307952017-08-30 17:42:54 +02001533 value = state->planes << 8 | GENERAL_UPDATE;
1534 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
1535 value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
1536
1537 value = state->planes | GENERAL_ACT_REQ;
1538 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
1539 value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
Thierry Reding4aa3df72014-11-24 16:27:13 +01001540}
1541
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001542static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
Thierry Reding4aa3df72014-11-24 16:27:13 +01001543 .atomic_check = tegra_crtc_atomic_check,
1544 .atomic_begin = tegra_crtc_atomic_begin,
1545 .atomic_flush = tegra_crtc_atomic_flush,
Laurent Pinchart0b20a0f2017-06-30 12:36:44 +03001546 .atomic_enable = tegra_crtc_atomic_enable,
Laurent Pinchart64581712017-06-30 12:36:45 +03001547 .atomic_disable = tegra_crtc_atomic_disable,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001548};
1549
Thierry Reding6e5ff992012-11-28 11:45:47 +01001550static irqreturn_t tegra_dc_irq(int irq, void *data)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001551{
1552 struct tegra_dc *dc = data;
1553 unsigned long status;
1554
1555 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
1556 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
1557
1558 if (status & FRAME_END_INT) {
1559 /*
1560 dev_dbg(dc->dev, "%s(): frame end\n", __func__);
1561 */
Thierry Reding791ddb12015-07-28 21:27:05 +02001562 dc->stats.frames++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001563 }
1564
1565 if (status & VBLANK_INT) {
1566 /*
1567 dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
1568 */
Thierry Redinged7dae52014-12-16 16:03:13 +01001569 drm_crtc_handle_vblank(&dc->base);
Thierry Reding791ddb12015-07-28 21:27:05 +02001570 dc->stats.vblank++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001571 }
1572
1573 if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
1574 /*
1575 dev_dbg(dc->dev, "%s(): underflow\n", __func__);
1576 */
Thierry Reding791ddb12015-07-28 21:27:05 +02001577 dc->stats.underflow++;
1578 }
1579
1580 if (status & (WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT)) {
1581 /*
1582 dev_dbg(dc->dev, "%s(): overflow\n", __func__);
1583 */
1584 dc->stats.overflow++;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001585 }
1586
Thierry Reding47307952017-08-30 17:42:54 +02001587 if (status & HEAD_UF_INT) {
1588 dev_dbg_ratelimited(dc->dev, "%s(): head underflow\n", __func__);
1589 dc->stats.underflow++;
1590 }
1591
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001592 return IRQ_HANDLED;
1593}
1594
Thierry Reding53fa7f72013-09-24 15:35:40 +02001595static int tegra_dc_init(struct host1x_client *client)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001596{
Thierry Reding9910f5c2014-05-22 09:57:15 +02001597 struct drm_device *drm = dev_get_drvdata(client->parent);
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001598 unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
Thierry Reding776dc382013-10-14 14:43:22 +02001599 struct tegra_dc *dc = host1x_client_to_dc(client);
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001600 struct tegra_drm *tegra = drm->dev_private;
Thierry Redingc7679302014-10-21 13:51:53 +02001601 struct drm_plane *primary = NULL;
1602 struct drm_plane *cursor = NULL;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001603 int err;
1604
Thierry Reding617dd7c2017-08-30 12:48:31 +02001605 dc->syncpt = host1x_syncpt_request(client, flags);
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001606 if (!dc->syncpt)
1607 dev_warn(dc->dev, "failed to allocate syncpoint\n");
1608
Thierry Redingdf06b752014-06-26 21:41:53 +02001609 if (tegra->domain) {
1610 err = iommu_attach_device(tegra->domain, dc->dev);
1611 if (err < 0) {
1612 dev_err(dc->dev, "failed to attach to domain: %d\n",
1613 err);
1614 return err;
1615 }
1616
1617 dc->domain = tegra->domain;
1618 }
1619
Thierry Reding47307952017-08-30 17:42:54 +02001620 if (dc->soc->wgrps)
1621 primary = tegra_dc_add_shared_planes(drm, dc);
1622 else
1623 primary = tegra_dc_add_planes(drm, dc);
1624
Thierry Redingc7679302014-10-21 13:51:53 +02001625 if (IS_ERR(primary)) {
1626 err = PTR_ERR(primary);
1627 goto cleanup;
1628 }
1629
1630 if (dc->soc->supports_cursor) {
1631 cursor = tegra_dc_cursor_plane_create(drm, dc);
1632 if (IS_ERR(cursor)) {
1633 err = PTR_ERR(cursor);
1634 goto cleanup;
1635 }
1636 }
1637
1638 err = drm_crtc_init_with_planes(drm, &dc->base, primary, cursor,
Ville Syrjäläf9882872015-12-09 16:19:31 +02001639 &tegra_crtc_funcs, NULL);
Thierry Redingc7679302014-10-21 13:51:53 +02001640 if (err < 0)
1641 goto cleanup;
1642
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001643 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1644
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001645 /*
1646 * Keep track of the minimum pitch alignment across all display
1647 * controllers.
1648 */
1649 if (dc->soc->pitch_align > tegra->pitch_align)
1650 tegra->pitch_align = dc->soc->pitch_align;
1651
Thierry Reding9910f5c2014-05-22 09:57:15 +02001652 err = tegra_dc_rgb_init(drm, dc);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001653 if (err < 0 && err != -ENODEV) {
1654 dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
Thierry Redingc7679302014-10-21 13:51:53 +02001655 goto cleanup;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001656 }
1657
Thierry Reding6e5ff992012-11-28 11:45:47 +01001658 err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001659 dev_name(dc->dev), dc);
1660 if (err < 0) {
1661 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
1662 err);
Thierry Redingc7679302014-10-21 13:51:53 +02001663 goto cleanup;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001664 }
1665
1666 return 0;
Thierry Redingc7679302014-10-21 13:51:53 +02001667
1668cleanup:
Thierry Reding47307952017-08-30 17:42:54 +02001669 if (!IS_ERR_OR_NULL(cursor))
Thierry Redingc7679302014-10-21 13:51:53 +02001670 drm_plane_cleanup(cursor);
1671
Thierry Reding47307952017-08-30 17:42:54 +02001672 if (!IS_ERR(primary))
Thierry Redingc7679302014-10-21 13:51:53 +02001673 drm_plane_cleanup(primary);
1674
1675 if (tegra->domain) {
1676 iommu_detach_device(tegra->domain, dc->dev);
1677 dc->domain = NULL;
1678 }
1679
1680 return err;
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001681}
1682
Thierry Reding53fa7f72013-09-24 15:35:40 +02001683static int tegra_dc_exit(struct host1x_client *client)
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001684{
Thierry Reding776dc382013-10-14 14:43:22 +02001685 struct tegra_dc *dc = host1x_client_to_dc(client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001686 int err;
1687
1688 devm_free_irq(dc->dev, dc->irq, dc);
1689
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001690 err = tegra_dc_rgb_exit(dc);
1691 if (err) {
1692 dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
1693 return err;
1694 }
1695
Thierry Redingdf06b752014-06-26 21:41:53 +02001696 if (dc->domain) {
1697 iommu_detach_device(dc->domain, dc->dev);
1698 dc->domain = NULL;
1699 }
1700
Thierry Reding2bcdcbf2015-08-24 14:47:10 +02001701 host1x_syncpt_free(dc->syncpt);
1702
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001703 return 0;
1704}
1705
1706static const struct host1x_client_ops dc_client_ops = {
Thierry Reding53fa7f72013-09-24 15:35:40 +02001707 .init = tegra_dc_init,
1708 .exit = tegra_dc_exit,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001709};
1710
Thierry Reding8620fc62013-12-12 11:03:59 +01001711static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001712 .supports_background_color = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001713 .supports_interlacing = false,
Thierry Redinge6876512013-12-20 13:58:33 +01001714 .supports_cursor = false,
Thierry Redingc134f012014-06-03 14:48:12 +02001715 .supports_block_linear = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001716 .pitch_align = 8,
Thierry Reding9c012702014-07-07 15:32:53 +02001717 .has_powergate = false,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001718 .broken_reset = true,
Thierry Reding47307952017-08-30 17:42:54 +02001719 .has_nvdisplay = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001720};
1721
1722static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001723 .supports_background_color = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001724 .supports_interlacing = false,
Thierry Redinge6876512013-12-20 13:58:33 +01001725 .supports_cursor = false,
Thierry Redingc134f012014-06-03 14:48:12 +02001726 .supports_block_linear = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001727 .pitch_align = 8,
Thierry Reding9c012702014-07-07 15:32:53 +02001728 .has_powergate = false,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001729 .broken_reset = false,
Thierry Reding47307952017-08-30 17:42:54 +02001730 .has_nvdisplay = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001731};
1732
1733static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001734 .supports_background_color = false,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001735 .supports_interlacing = false,
1736 .supports_cursor = false,
1737 .supports_block_linear = false,
1738 .pitch_align = 64,
Thierry Reding9c012702014-07-07 15:32:53 +02001739 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001740 .broken_reset = false,
Thierry Reding47307952017-08-30 17:42:54 +02001741 .has_nvdisplay = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001742};
1743
1744static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001745 .supports_background_color = true,
Thierry Reding8620fc62013-12-12 11:03:59 +01001746 .supports_interlacing = true,
Thierry Redinge6876512013-12-20 13:58:33 +01001747 .supports_cursor = true,
Thierry Redingc134f012014-06-03 14:48:12 +02001748 .supports_block_linear = true,
Thierry Redingd1f3e1e2014-07-11 08:29:14 +02001749 .pitch_align = 64,
Thierry Reding9c012702014-07-07 15:32:53 +02001750 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001751 .broken_reset = false,
Thierry Reding47307952017-08-30 17:42:54 +02001752 .has_nvdisplay = false,
Thierry Reding8620fc62013-12-12 11:03:59 +01001753};
1754
Thierry Reding5b4f5162015-03-27 10:31:58 +01001755static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
Thierry Reding7116e9a2017-11-13 11:20:48 +01001756 .supports_background_color = true,
Thierry Reding5b4f5162015-03-27 10:31:58 +01001757 .supports_interlacing = true,
1758 .supports_cursor = true,
1759 .supports_block_linear = true,
1760 .pitch_align = 64,
1761 .has_powergate = true,
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001762 .broken_reset = false,
Thierry Reding47307952017-08-30 17:42:54 +02001763 .has_nvdisplay = false,
1764};
1765
1766static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
1767 {
1768 .index = 0,
1769 .dc = 0,
1770 .windows = (const unsigned int[]) { 0 },
1771 .num_windows = 1,
1772 }, {
1773 .index = 1,
1774 .dc = 1,
1775 .windows = (const unsigned int[]) { 1 },
1776 .num_windows = 1,
1777 }, {
1778 .index = 2,
1779 .dc = 1,
1780 .windows = (const unsigned int[]) { 2 },
1781 .num_windows = 1,
1782 }, {
1783 .index = 3,
1784 .dc = 2,
1785 .windows = (const unsigned int[]) { 3 },
1786 .num_windows = 1,
1787 }, {
1788 .index = 4,
1789 .dc = 2,
1790 .windows = (const unsigned int[]) { 4 },
1791 .num_windows = 1,
1792 }, {
1793 .index = 5,
1794 .dc = 2,
1795 .windows = (const unsigned int[]) { 5 },
1796 .num_windows = 1,
1797 },
1798};
1799
1800static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
1801 .supports_background_color = true,
1802 .supports_interlacing = true,
1803 .supports_cursor = true,
1804 .supports_block_linear = true,
1805 .pitch_align = 64,
1806 .has_powergate = false,
1807 .broken_reset = false,
1808 .has_nvdisplay = true,
1809 .wgrps = tegra186_dc_wgrps,
1810 .num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps),
Thierry Reding5b4f5162015-03-27 10:31:58 +01001811};
1812
Thierry Reding8620fc62013-12-12 11:03:59 +01001813static const struct of_device_id tegra_dc_of_match[] = {
1814 {
Thierry Reding47307952017-08-30 17:42:54 +02001815 .compatible = "nvidia,tegra186-dc",
1816 .data = &tegra186_dc_soc_info,
1817 }, {
Thierry Reding5b4f5162015-03-27 10:31:58 +01001818 .compatible = "nvidia,tegra210-dc",
1819 .data = &tegra210_dc_soc_info,
1820 }, {
Thierry Reding8620fc62013-12-12 11:03:59 +01001821 .compatible = "nvidia,tegra124-dc",
1822 .data = &tegra124_dc_soc_info,
1823 }, {
Thierry Reding9c012702014-07-07 15:32:53 +02001824 .compatible = "nvidia,tegra114-dc",
1825 .data = &tegra114_dc_soc_info,
1826 }, {
Thierry Reding8620fc62013-12-12 11:03:59 +01001827 .compatible = "nvidia,tegra30-dc",
1828 .data = &tegra30_dc_soc_info,
1829 }, {
1830 .compatible = "nvidia,tegra20-dc",
1831 .data = &tegra20_dc_soc_info,
1832 }, {
1833 /* sentinel */
1834 }
1835};
Stephen Warrenef707282014-06-18 16:21:55 -06001836MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
Thierry Reding8620fc62013-12-12 11:03:59 +01001837
Thierry Reding13411dd2014-01-09 17:08:36 +01001838static int tegra_dc_parse_dt(struct tegra_dc *dc)
1839{
1840 struct device_node *np;
1841 u32 value = 0;
1842 int err;
1843
1844 err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);
1845 if (err < 0) {
1846 dev_err(dc->dev, "missing \"nvidia,head\" property\n");
1847
1848 /*
1849 * If the nvidia,head property isn't present, try to find the
1850 * correct head number by looking up the position of this
1851 * display controller's node within the device tree. Assuming
1852 * that the nodes are ordered properly in the DTS file and
1853 * that the translation into a flattened device tree blob
1854 * preserves that ordering this will actually yield the right
1855 * head number.
1856 *
1857 * If those assumptions don't hold, this will still work for
1858 * cases where only a single display controller is used.
1859 */
1860 for_each_matching_node(np, tegra_dc_of_match) {
Julia Lawallcf6b1742015-10-24 16:42:31 +02001861 if (np == dc->dev->of_node) {
1862 of_node_put(np);
Thierry Reding13411dd2014-01-09 17:08:36 +01001863 break;
Julia Lawallcf6b1742015-10-24 16:42:31 +02001864 }
Thierry Reding13411dd2014-01-09 17:08:36 +01001865
1866 value++;
1867 }
1868 }
1869
1870 dc->pipe = value;
1871
1872 return 0;
1873}
1874
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001875static int tegra_dc_probe(struct platform_device *pdev)
1876{
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001877 struct resource *regs;
1878 struct tegra_dc *dc;
1879 int err;
1880
1881 dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
1882 if (!dc)
1883 return -ENOMEM;
1884
Thierry Redingb9ff7ae2017-08-21 16:35:17 +02001885 dc->soc = of_device_get_match_data(&pdev->dev);
Thierry Reding8620fc62013-12-12 11:03:59 +01001886
Thierry Reding6e5ff992012-11-28 11:45:47 +01001887 spin_lock_init(&dc->lock);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001888 INIT_LIST_HEAD(&dc->list);
1889 dc->dev = &pdev->dev;
1890
Thierry Reding13411dd2014-01-09 17:08:36 +01001891 err = tegra_dc_parse_dt(dc);
1892 if (err < 0)
1893 return err;
1894
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001895 dc->clk = devm_clk_get(&pdev->dev, NULL);
1896 if (IS_ERR(dc->clk)) {
1897 dev_err(&pdev->dev, "failed to get clock\n");
1898 return PTR_ERR(dc->clk);
1899 }
1900
Stephen Warrenca480802013-11-06 16:20:54 -07001901 dc->rst = devm_reset_control_get(&pdev->dev, "dc");
1902 if (IS_ERR(dc->rst)) {
1903 dev_err(&pdev->dev, "failed to get reset\n");
1904 return PTR_ERR(dc->rst);
1905 }
1906
Thierry Redinga2f2f742017-08-30 17:41:00 +02001907 /* assert reset and disable clock */
1908 if (!dc->soc->broken_reset) {
1909 err = clk_prepare_enable(dc->clk);
1910 if (err < 0)
1911 return err;
1912
1913 usleep_range(2000, 4000);
1914
1915 err = reset_control_assert(dc->rst);
1916 if (err < 0)
1917 return err;
1918
1919 usleep_range(2000, 4000);
1920
1921 clk_disable_unprepare(dc->clk);
1922 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02001923
Thierry Reding9c012702014-07-07 15:32:53 +02001924 if (dc->soc->has_powergate) {
1925 if (dc->pipe == 0)
1926 dc->powergate = TEGRA_POWERGATE_DIS;
1927 else
1928 dc->powergate = TEGRA_POWERGATE_DISB;
1929
Thierry Reding33a8eb82015-08-03 13:20:49 +02001930 tegra_powergate_power_off(dc->powergate);
Thierry Reding9c012702014-07-07 15:32:53 +02001931 }
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001932
1933 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Thierry Redingd4ed6022013-01-21 11:09:02 +01001934 dc->regs = devm_ioremap_resource(&pdev->dev, regs);
1935 if (IS_ERR(dc->regs))
1936 return PTR_ERR(dc->regs);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001937
1938 dc->irq = platform_get_irq(pdev, 0);
1939 if (dc->irq < 0) {
1940 dev_err(&pdev->dev, "failed to get IRQ\n");
1941 return -ENXIO;
1942 }
1943
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001944 err = tegra_dc_rgb_probe(dc);
1945 if (err < 0 && err != -ENODEV) {
1946 dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
1947 return err;
1948 }
1949
Thierry Reding33a8eb82015-08-03 13:20:49 +02001950 platform_set_drvdata(pdev, dc);
1951 pm_runtime_enable(&pdev->dev);
1952
1953 INIT_LIST_HEAD(&dc->client.list);
1954 dc->client.ops = &dc_client_ops;
1955 dc->client.dev = &pdev->dev;
1956
Thierry Reding776dc382013-10-14 14:43:22 +02001957 err = host1x_client_register(&dc->client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001958 if (err < 0) {
1959 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1960 err);
1961 return err;
1962 }
1963
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001964 return 0;
1965}
1966
1967static int tegra_dc_remove(struct platform_device *pdev)
1968{
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001969 struct tegra_dc *dc = platform_get_drvdata(pdev);
1970 int err;
1971
Thierry Reding776dc382013-10-14 14:43:22 +02001972 err = host1x_client_unregister(&dc->client);
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00001973 if (err < 0) {
1974 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1975 err);
1976 return err;
1977 }
1978
Thierry Reding59d29c02013-10-14 14:26:42 +02001979 err = tegra_dc_rgb_remove(dc);
1980 if (err < 0) {
1981 dev_err(&pdev->dev, "failed to remove RGB output: %d\n", err);
1982 return err;
1983 }
1984
Thierry Reding33a8eb82015-08-03 13:20:49 +02001985 pm_runtime_disable(&pdev->dev);
1986
1987 return 0;
1988}
1989
1990#ifdef CONFIG_PM
1991static int tegra_dc_suspend(struct device *dev)
1992{
1993 struct tegra_dc *dc = dev_get_drvdata(dev);
1994 int err;
1995
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03001996 if (!dc->soc->broken_reset) {
1997 err = reset_control_assert(dc->rst);
1998 if (err < 0) {
1999 dev_err(dev, "failed to assert reset: %d\n", err);
2000 return err;
2001 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02002002 }
Thierry Reding9c012702014-07-07 15:32:53 +02002003
2004 if (dc->soc->has_powergate)
2005 tegra_powergate_power_off(dc->powergate);
2006
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00002007 clk_disable_unprepare(dc->clk);
2008
2009 return 0;
2010}
2011
Thierry Reding33a8eb82015-08-03 13:20:49 +02002012static int tegra_dc_resume(struct device *dev)
2013{
2014 struct tegra_dc *dc = dev_get_drvdata(dev);
2015 int err;
2016
2017 if (dc->soc->has_powergate) {
2018 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
2019 dc->rst);
2020 if (err < 0) {
2021 dev_err(dev, "failed to power partition: %d\n", err);
2022 return err;
2023 }
2024 } else {
2025 err = clk_prepare_enable(dc->clk);
2026 if (err < 0) {
2027 dev_err(dev, "failed to enable clock: %d\n", err);
2028 return err;
2029 }
2030
Dmitry Osipenko6ac15712017-06-15 02:18:29 +03002031 if (!dc->soc->broken_reset) {
2032 err = reset_control_deassert(dc->rst);
2033 if (err < 0) {
2034 dev_err(dev,
2035 "failed to deassert reset: %d\n", err);
2036 return err;
2037 }
Thierry Reding33a8eb82015-08-03 13:20:49 +02002038 }
2039 }
2040
2041 return 0;
2042}
2043#endif
2044
2045static const struct dev_pm_ops tegra_dc_pm_ops = {
2046 SET_RUNTIME_PM_OPS(tegra_dc_suspend, tegra_dc_resume, NULL)
2047};
2048
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00002049struct platform_driver tegra_dc_driver = {
2050 .driver = {
2051 .name = "tegra-dc",
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00002052 .of_match_table = tegra_dc_of_match,
Thierry Reding33a8eb82015-08-03 13:20:49 +02002053 .pm = &tegra_dc_pm_ops,
Thierry Redingd8f4a9e2012-11-15 21:28:22 +00002054 },
2055 .probe = tegra_dc_probe,
2056 .remove = tegra_dc_remove,
2057};