• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2017 NVIDIA CORPORATION.  All rights reserved.
4  */
5 
6 #include <linux/clk.h>
7 #include <linux/delay.h>
8 #include <linux/dma-mapping.h>
9 #include <linux/host1x.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/of_graph.h>
13 #include <linux/of_platform.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/reset.h>
17 
18 #include <drm/drm_atomic.h>
19 #include <drm/drm_atomic_helper.h>
20 #include <drm/drm_blend.h>
21 #include <drm/drm_fourcc.h>
22 #include <drm/drm_framebuffer.h>
23 #include <drm/drm_probe_helper.h>
24 
25 #include "drm.h"
26 #include "dc.h"
27 #include "plane.h"
28 
29 #define NFB 24
30 
31 static const u32 tegra_shared_plane_formats[] = {
32 	DRM_FORMAT_ARGB1555,
33 	DRM_FORMAT_RGB565,
34 	DRM_FORMAT_RGBA5551,
35 	DRM_FORMAT_ARGB8888,
36 	DRM_FORMAT_ABGR8888,
37 	/* new on Tegra114 */
38 	DRM_FORMAT_ABGR4444,
39 	DRM_FORMAT_ABGR1555,
40 	DRM_FORMAT_BGRA5551,
41 	DRM_FORMAT_XRGB1555,
42 	DRM_FORMAT_RGBX5551,
43 	DRM_FORMAT_XBGR1555,
44 	DRM_FORMAT_BGRX5551,
45 	DRM_FORMAT_BGR565,
46 	DRM_FORMAT_XRGB8888,
47 	DRM_FORMAT_XBGR8888,
48 	/* planar formats */
49 	DRM_FORMAT_UYVY,
50 	DRM_FORMAT_YUYV,
51 	DRM_FORMAT_YUV420,
52 	DRM_FORMAT_YUV422,
53 };
54 
55 static const u64 tegra_shared_plane_modifiers[] = {
56 	DRM_FORMAT_MOD_LINEAR,
57 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
58 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
59 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
60 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
61 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
62 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
63 	/*
64 	 * The GPU sector layout is only supported on Tegra194, but these will
65 	 * be filtered out later on by ->format_mod_supported() on SoCs where
66 	 * it isn't supported.
67 	 */
68 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
69 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
70 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
71 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
72 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
73 	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT,
74 	/* sentinel */
75 	DRM_FORMAT_MOD_INVALID
76 };
77 
tegra_plane_offset(struct tegra_plane * plane,unsigned int offset)78 static inline unsigned int tegra_plane_offset(struct tegra_plane *plane,
79 					      unsigned int offset)
80 {
81 	if (offset >= 0x500 && offset <= 0x581) {
82 		offset = 0x000 + (offset - 0x500);
83 		return plane->offset + offset;
84 	}
85 
86 	if (offset >= 0x700 && offset <= 0x73c) {
87 		offset = 0x180 + (offset - 0x700);
88 		return plane->offset + offset;
89 	}
90 
91 	if (offset >= 0x800 && offset <= 0x83e) {
92 		offset = 0x1c0 + (offset - 0x800);
93 		return plane->offset + offset;
94 	}
95 
96 	dev_WARN(plane->dc->dev, "invalid offset: %x\n", offset);
97 
98 	return plane->offset + offset;
99 }
100 
tegra_plane_readl(struct tegra_plane * plane,unsigned int offset)101 static inline u32 tegra_plane_readl(struct tegra_plane *plane,
102 				    unsigned int offset)
103 {
104 	return tegra_dc_readl(plane->dc, tegra_plane_offset(plane, offset));
105 }
106 
tegra_plane_writel(struct tegra_plane * plane,u32 value,unsigned int offset)107 static inline void tegra_plane_writel(struct tegra_plane *plane, u32 value,
108 				      unsigned int offset)
109 {
110 	tegra_dc_writel(plane->dc, value, tegra_plane_offset(plane, offset));
111 }
112 
tegra_windowgroup_enable(struct tegra_windowgroup * wgrp)113 static int tegra_windowgroup_enable(struct tegra_windowgroup *wgrp)
114 {
115 	int err = 0;
116 
117 	mutex_lock(&wgrp->lock);
118 
119 	if (wgrp->usecount == 0) {
120 		err = host1x_client_resume(wgrp->parent);
121 		if (err < 0) {
122 			dev_err(wgrp->parent->dev, "failed to resume: %d\n", err);
123 			goto unlock;
124 		}
125 
126 		reset_control_deassert(wgrp->rst);
127 	}
128 
129 	wgrp->usecount++;
130 
131 unlock:
132 	mutex_unlock(&wgrp->lock);
133 	return err;
134 }
135 
tegra_windowgroup_disable(struct tegra_windowgroup * wgrp)136 static void tegra_windowgroup_disable(struct tegra_windowgroup *wgrp)
137 {
138 	int err;
139 
140 	mutex_lock(&wgrp->lock);
141 
142 	if (wgrp->usecount == 1) {
143 		err = reset_control_assert(wgrp->rst);
144 		if (err < 0) {
145 			pr_err("failed to assert reset for window group %u\n",
146 			       wgrp->index);
147 		}
148 
149 		host1x_client_suspend(wgrp->parent);
150 	}
151 
152 	wgrp->usecount--;
153 	mutex_unlock(&wgrp->lock);
154 }
155 
tegra_display_hub_prepare(struct tegra_display_hub * hub)156 int tegra_display_hub_prepare(struct tegra_display_hub *hub)
157 {
158 	unsigned int i;
159 
160 	/*
161 	 * XXX Enabling/disabling windowgroups needs to happen when the owner
162 	 * display controller is disabled. There's currently no good point at
163 	 * which this could be executed, so unconditionally enable all window
164 	 * groups for now.
165 	 */
166 	for (i = 0; i < hub->soc->num_wgrps; i++) {
167 		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
168 
169 		/* Skip orphaned window group whose parent DC is disabled */
170 		if (wgrp->parent)
171 			tegra_windowgroup_enable(wgrp);
172 	}
173 
174 	return 0;
175 }
176 
tegra_display_hub_cleanup(struct tegra_display_hub * hub)177 void tegra_display_hub_cleanup(struct tegra_display_hub *hub)
178 {
179 	unsigned int i;
180 
181 	/*
182 	 * XXX Remove this once window groups can be more fine-grainedly
183 	 * enabled and disabled.
184 	 */
185 	for (i = 0; i < hub->soc->num_wgrps; i++) {
186 		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
187 
188 		/* Skip orphaned window group whose parent DC is disabled */
189 		if (wgrp->parent)
190 			tegra_windowgroup_disable(wgrp);
191 	}
192 }
193 
tegra_shared_plane_update(struct tegra_plane * plane)194 static void tegra_shared_plane_update(struct tegra_plane *plane)
195 {
196 	struct tegra_dc *dc = plane->dc;
197 	unsigned long timeout;
198 	u32 mask, value;
199 
200 	mask = COMMON_UPDATE | WIN_A_UPDATE << plane->base.index;
201 	tegra_dc_writel(dc, mask, DC_CMD_STATE_CONTROL);
202 
203 	timeout = jiffies + msecs_to_jiffies(1000);
204 
205 	while (time_before(jiffies, timeout)) {
206 		value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
207 		if ((value & mask) == 0)
208 			break;
209 
210 		usleep_range(100, 400);
211 	}
212 }
213 
tegra_shared_plane_activate(struct tegra_plane * plane)214 static void tegra_shared_plane_activate(struct tegra_plane *plane)
215 {
216 	struct tegra_dc *dc = plane->dc;
217 	unsigned long timeout;
218 	u32 mask, value;
219 
220 	mask = COMMON_ACTREQ | WIN_A_ACT_REQ << plane->base.index;
221 	tegra_dc_writel(dc, mask, DC_CMD_STATE_CONTROL);
222 
223 	timeout = jiffies + msecs_to_jiffies(1000);
224 
225 	while (time_before(jiffies, timeout)) {
226 		value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
227 		if ((value & mask) == 0)
228 			break;
229 
230 		usleep_range(100, 400);
231 	}
232 }
233 
234 static unsigned int
tegra_shared_plane_get_owner(struct tegra_plane * plane,struct tegra_dc * dc)235 tegra_shared_plane_get_owner(struct tegra_plane *plane, struct tegra_dc *dc)
236 {
237 	unsigned int offset =
238 		tegra_plane_offset(plane, DC_WIN_CORE_WINDOWGROUP_SET_CONTROL);
239 
240 	return tegra_dc_readl(dc, offset) & OWNER_MASK;
241 }
242 
tegra_dc_owns_shared_plane(struct tegra_dc * dc,struct tegra_plane * plane)243 static bool tegra_dc_owns_shared_plane(struct tegra_dc *dc,
244 				       struct tegra_plane *plane)
245 {
246 	struct device *dev = dc->dev;
247 
248 	if (tegra_shared_plane_get_owner(plane, dc) == dc->pipe) {
249 		if (plane->dc == dc)
250 			return true;
251 
252 		dev_WARN(dev, "head %u owns window %u but is not attached\n",
253 			 dc->pipe, plane->index);
254 	}
255 
256 	return false;
257 }
258 
tegra_shared_plane_set_owner(struct tegra_plane * plane,struct tegra_dc * new)259 static int tegra_shared_plane_set_owner(struct tegra_plane *plane,
260 					struct tegra_dc *new)
261 {
262 	unsigned int offset =
263 		tegra_plane_offset(plane, DC_WIN_CORE_WINDOWGROUP_SET_CONTROL);
264 	struct tegra_dc *old = plane->dc, *dc = new ? new : old;
265 	struct device *dev = new ? new->dev : old->dev;
266 	unsigned int owner, index = plane->index;
267 	u32 value;
268 
269 	value = tegra_dc_readl(dc, offset);
270 	owner = value & OWNER_MASK;
271 
272 	if (new && (owner != OWNER_MASK && owner != new->pipe)) {
273 		dev_WARN(dev, "window %u owned by head %u\n", index, owner);
274 		return -EBUSY;
275 	}
276 
277 	/*
278 	 * This seems to happen whenever the head has been disabled with one
279 	 * or more windows being active. This is harmless because we'll just
280 	 * reassign the window to the new head anyway.
281 	 */
282 	if (old && owner == OWNER_MASK)
283 		dev_dbg(dev, "window %u not owned by head %u but %u\n", index,
284 			old->pipe, owner);
285 
286 	value &= ~OWNER_MASK;
287 
288 	if (new)
289 		value |= OWNER(new->pipe);
290 	else
291 		value |= OWNER_MASK;
292 
293 	tegra_dc_writel(dc, value, offset);
294 
295 	plane->dc = new;
296 
297 	return 0;
298 }
299 
tegra_shared_plane_setup_scaler(struct tegra_plane * plane)300 static void tegra_shared_plane_setup_scaler(struct tegra_plane *plane)
301 {
302 	static const unsigned int coeffs[192] = {
303 		0x00000000, 0x3c70e400, 0x3bb037e4, 0x0c51cc9c,
304 		0x00100001, 0x3bf0dbfa, 0x3d00f406, 0x3fe003ff,
305 		0x00300002, 0x3b80cbf5, 0x3da1040d, 0x3fb003fe,
306 		0x00400002, 0x3b20bff1, 0x3e511015, 0x3f9003fc,
307 		0x00500002, 0x3ad0b3ed, 0x3f21201d, 0x3f5003fb,
308 		0x00500003, 0x3aa0a3e9, 0x3ff13026, 0x3f2007f9,
309 		0x00500403, 0x3a7097e6, 0x00e1402f, 0x3ee007f7,
310 		0x00500403, 0x3a608be4, 0x01d14c38, 0x3ea00bf6,
311 		0x00500403, 0x3a507fe2, 0x02e15c42, 0x3e500ff4,
312 		0x00500402, 0x3a6073e1, 0x03f16c4d, 0x3e000ff2,
313 		0x00400402, 0x3a706be0, 0x05117858, 0x3db013f0,
314 		0x00300402, 0x3a905fe0, 0x06318863, 0x3d6017ee,
315 		0x00300402, 0x3ab057e0, 0x0771986e, 0x3d001beb,
316 		0x00200001, 0x3af04fe1, 0x08a1a47a, 0x3cb023e9,
317 		0x00100001, 0x3b2047e2, 0x09e1b485, 0x3c6027e7,
318 		0x00100000, 0x3b703fe2, 0x0b11c091, 0x3c002fe6,
319 		0x3f203800, 0x0391103f, 0x3ff0a014, 0x0811606c,
320 		0x3f2037ff, 0x0351083c, 0x03e11842, 0x3f203c00,
321 		0x3f302fff, 0x03010439, 0x04311c45, 0x3f104401,
322 		0x3f302fff, 0x02c0fc35, 0x04812448, 0x3f104802,
323 		0x3f4027ff, 0x0270f832, 0x04c1284b, 0x3f205003,
324 		0x3f4023ff, 0x0230f030, 0x0511304e, 0x3f205403,
325 		0x3f601fff, 0x01f0e82d, 0x05613451, 0x3f205c04,
326 		0x3f701bfe, 0x01b0e02a, 0x05a13c54, 0x3f306006,
327 		0x3f7017fe, 0x0170d827, 0x05f14057, 0x3f406807,
328 		0x3f8017ff, 0x0140d424, 0x0641445a, 0x3f406c08,
329 		0x3fa013ff, 0x0100cc22, 0x0681485d, 0x3f507409,
330 		0x3fa00fff, 0x00d0c41f, 0x06d14c60, 0x3f607c0b,
331 		0x3fc00fff, 0x0090bc1c, 0x07115063, 0x3f80840c,
332 		0x3fd00bff, 0x0070b41a, 0x07515465, 0x3f908c0e,
333 		0x3fe007ff, 0x0040b018, 0x07915868, 0x3fb0900f,
334 		0x3ff00400, 0x0010a816, 0x07d15c6a, 0x3fd09811,
335 		0x00a04c0e, 0x0460f442, 0x0240a827, 0x05c15859,
336 		0x0090440d, 0x0440f040, 0x0480fc43, 0x00b05010,
337 		0x0080400c, 0x0410ec3e, 0x04910044, 0x00d05411,
338 		0x0070380b, 0x03f0e83d, 0x04b10846, 0x00e05812,
339 		0x0060340a, 0x03d0e43b, 0x04d10c48, 0x00f06013,
340 		0x00503009, 0x03b0e039, 0x04e11449, 0x01106415,
341 		0x00402c08, 0x0390d838, 0x05011c4b, 0x01206c16,
342 		0x00302807, 0x0370d436, 0x0511204c, 0x01407018,
343 		0x00302406, 0x0340d034, 0x0531244e, 0x01507419,
344 		0x00202005, 0x0320cc32, 0x05412c50, 0x01707c1b,
345 		0x00101c04, 0x0300c431, 0x05613451, 0x0180801d,
346 		0x00101803, 0x02e0c02f, 0x05713853, 0x01a0881e,
347 		0x00101002, 0x02b0bc2d, 0x05814054, 0x01c08c20,
348 		0x00000c02, 0x02a0b82c, 0x05914455, 0x01e09421,
349 		0x00000801, 0x0280b02a, 0x05a14c57, 0x02009c23,
350 		0x00000400, 0x0260ac28, 0x05b15458, 0x0220a025,
351 	};
352 	unsigned int ratio, row, column;
353 
354 	for (ratio = 0; ratio <= 2; ratio++) {
355 		for (row = 0; row <= 15; row++) {
356 			for (column = 0; column <= 3; column++) {
357 				unsigned int index = (ratio << 6) + (row << 2) + column;
358 				u32 value;
359 
360 				value = COEFF_INDEX(index) | COEFF_DATA(coeffs[index]);
361 				tegra_plane_writel(plane, value,
362 						   DC_WIN_WINDOWGROUP_SET_INPUT_SCALER_COEFF);
363 			}
364 		}
365 	}
366 }
367 
tegra_dc_assign_shared_plane(struct tegra_dc * dc,struct tegra_plane * plane)368 static void tegra_dc_assign_shared_plane(struct tegra_dc *dc,
369 					 struct tegra_plane *plane)
370 {
371 	u32 value;
372 	int err;
373 
374 	if (!tegra_dc_owns_shared_plane(dc, plane)) {
375 		err = tegra_shared_plane_set_owner(plane, dc);
376 		if (err < 0)
377 			return;
378 	}
379 
380 	value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_LINEBUF_CONFIG);
381 	value |= MODE_FOUR_LINES;
382 	tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_LINEBUF_CONFIG);
383 
384 	value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_WGRP_FETCH_METER);
385 	value = SLOTS(1);
386 	tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_WGRP_FETCH_METER);
387 
388 	/* disable watermark */
389 	value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLA);
390 	value &= ~LATENCY_CTL_MODE_ENABLE;
391 	tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLA);
392 
393 	value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLB);
394 	value |= WATERMARK_MASK;
395 	tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLB);
396 
397 	/* pipe meter */
398 	value = tegra_plane_readl(plane, DC_WIN_CORE_PRECOMP_WGRP_PIPE_METER);
399 	value = PIPE_METER_INT(0) | PIPE_METER_FRAC(0);
400 	tegra_plane_writel(plane, value, DC_WIN_CORE_PRECOMP_WGRP_PIPE_METER);
401 
402 	/* mempool entries */
403 	value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_WGRP_POOL_CONFIG);
404 	value = MEMPOOL_ENTRIES(0x331);
405 	tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_WGRP_POOL_CONFIG);
406 
407 	value = tegra_plane_readl(plane, DC_WIN_CORE_IHUB_THREAD_GROUP);
408 	value &= ~THREAD_NUM_MASK;
409 	value |= THREAD_NUM(plane->base.index);
410 	value |= THREAD_GROUP_ENABLE;
411 	tegra_plane_writel(plane, value, DC_WIN_CORE_IHUB_THREAD_GROUP);
412 
413 	tegra_shared_plane_setup_scaler(plane);
414 
415 	tegra_shared_plane_update(plane);
416 	tegra_shared_plane_activate(plane);
417 }
418 
tegra_dc_remove_shared_plane(struct tegra_dc * dc,struct tegra_plane * plane)419 static void tegra_dc_remove_shared_plane(struct tegra_dc *dc,
420 					 struct tegra_plane *plane)
421 {
422 	tegra_shared_plane_set_owner(plane, NULL);
423 }
424 
tegra_shared_plane_atomic_check(struct drm_plane * plane,struct drm_atomic_state * state)425 static int tegra_shared_plane_atomic_check(struct drm_plane *plane,
426 					   struct drm_atomic_state *state)
427 {
428 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
429 										 plane);
430 	struct tegra_plane_state *plane_state = to_tegra_plane_state(new_plane_state);
431 	struct tegra_shared_plane *tegra = to_tegra_shared_plane(plane);
432 	struct tegra_bo_tiling *tiling = &plane_state->tiling;
433 	struct tegra_dc *dc = to_tegra_dc(new_plane_state->crtc);
434 	int err;
435 
436 	/* no need for further checks if the plane is being disabled */
437 	if (!new_plane_state->crtc || !new_plane_state->fb)
438 		return 0;
439 
440 	err = tegra_plane_format(new_plane_state->fb->format->format,
441 				 &plane_state->format,
442 				 &plane_state->swap);
443 	if (err < 0)
444 		return err;
445 
446 	err = tegra_fb_get_tiling(new_plane_state->fb, tiling);
447 	if (err < 0)
448 		return err;
449 
450 	if (tiling->mode == TEGRA_BO_TILING_MODE_BLOCK &&
451 	    !dc->soc->supports_block_linear) {
452 		DRM_ERROR("hardware doesn't support block linear mode\n");
453 		return -EINVAL;
454 	}
455 
456 	if (tiling->sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU &&
457 	    !dc->soc->supports_sector_layout) {
458 		DRM_ERROR("hardware doesn't support GPU sector layout\n");
459 		return -EINVAL;
460 	}
461 
462 	/*
463 	 * Tegra doesn't support different strides for U and V planes so we
464 	 * error out if the user tries to display a framebuffer with such a
465 	 * configuration.
466 	 */
467 	if (new_plane_state->fb->format->num_planes > 2) {
468 		if (new_plane_state->fb->pitches[2] != new_plane_state->fb->pitches[1]) {
469 			DRM_ERROR("unsupported UV-plane configuration\n");
470 			return -EINVAL;
471 		}
472 	}
473 
474 	/* XXX scaling is not yet supported, add a check here */
475 
476 	err = tegra_plane_state_add(&tegra->base, new_plane_state);
477 	if (err < 0)
478 		return err;
479 
480 	return 0;
481 }
482 
tegra_shared_plane_atomic_disable(struct drm_plane * plane,struct drm_atomic_state * state)483 static void tegra_shared_plane_atomic_disable(struct drm_plane *plane,
484 					      struct drm_atomic_state *state)
485 {
486 	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
487 									   plane);
488 	struct tegra_plane *p = to_tegra_plane(plane);
489 	struct tegra_dc *dc;
490 	u32 value;
491 	int err;
492 
493 	/* rien ne va plus */
494 	if (!old_state || !old_state->crtc)
495 		return;
496 
497 	dc = to_tegra_dc(old_state->crtc);
498 
499 	err = host1x_client_resume(&dc->client);
500 	if (err < 0) {
501 		dev_err(dc->dev, "failed to resume: %d\n", err);
502 		return;
503 	}
504 
505 	/*
506 	 * XXX Legacy helpers seem to sometimes call ->atomic_disable() even
507 	 * on planes that are already disabled. Make sure we fallback to the
508 	 * head for this particular state instead of crashing.
509 	 */
510 	if (WARN_ON(p->dc == NULL))
511 		p->dc = dc;
512 
513 	value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS);
514 	value &= ~WIN_ENABLE;
515 	tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS);
516 
517 	tegra_dc_remove_shared_plane(dc, p);
518 
519 	host1x_client_suspend(&dc->client);
520 }
521 
compute_phase_incr(fixed20_12 in,unsigned int out)522 static inline u32 compute_phase_incr(fixed20_12 in, unsigned int out)
523 {
524 	u64 tmp, tmp1, tmp2;
525 
526 	tmp = (u64)dfixed_trunc(in);
527 	tmp2 = (u64)out;
528 	tmp1 = (tmp << NFB) + (tmp2 >> 1);
529 	do_div(tmp1, tmp2);
530 
531 	return lower_32_bits(tmp1);
532 }
533 
tegra_shared_plane_atomic_update(struct drm_plane * plane,struct drm_atomic_state * state)534 static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
535 					     struct drm_atomic_state *state)
536 {
537 	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
538 									   plane);
539 	struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state);
540 	struct tegra_dc *dc = to_tegra_dc(new_state->crtc);
541 	unsigned int zpos = new_state->normalized_zpos;
542 	struct drm_framebuffer *fb = new_state->fb;
543 	struct tegra_plane *p = to_tegra_plane(plane);
544 	u32 value, min_width, bypass = 0;
545 	dma_addr_t base, addr_flag = 0;
546 	unsigned int bpc, planes;
547 	bool yuv;
548 	int err;
549 
550 	/* rien ne va plus */
551 	if (!new_state->crtc || !new_state->fb)
552 		return;
553 
554 	if (!new_state->visible) {
555 		tegra_shared_plane_atomic_disable(plane, state);
556 		return;
557 	}
558 
559 	err = host1x_client_resume(&dc->client);
560 	if (err < 0) {
561 		dev_err(dc->dev, "failed to resume: %d\n", err);
562 		return;
563 	}
564 
565 	yuv = tegra_plane_format_is_yuv(tegra_plane_state->format, &planes, &bpc);
566 
567 	tegra_dc_assign_shared_plane(dc, p);
568 
569 	tegra_plane_writel(p, VCOUNTER, DC_WIN_CORE_ACT_CONTROL);
570 
571 	/* blending */
572 	value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 |
573 		BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC |
574 		BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC;
575 	tegra_plane_writel(p, value, DC_WIN_BLEND_MATCH_SELECT);
576 
577 	value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 |
578 		BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC |
579 		BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC;
580 	tegra_plane_writel(p, value, DC_WIN_BLEND_NOMATCH_SELECT);
581 
582 	value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - zpos);
583 	tegra_plane_writel(p, value, DC_WIN_BLEND_LAYER_CONTROL);
584 
585 	/* scaling */
586 	min_width = min(new_state->src_w >> 16, new_state->crtc_w);
587 
588 	value = tegra_plane_readl(p, DC_WINC_PRECOMP_WGRP_PIPE_CAPC);
589 
590 	if (min_width < MAX_PIXELS_5TAP444(value)) {
591 		value = HORIZONTAL_TAPS_5 | VERTICAL_TAPS_5;
592 	} else {
593 		value = tegra_plane_readl(p, DC_WINC_PRECOMP_WGRP_PIPE_CAPE);
594 
595 		if (min_width < MAX_PIXELS_2TAP444(value))
596 			value = HORIZONTAL_TAPS_2 | VERTICAL_TAPS_2;
597 		else
598 			dev_err(dc->dev, "invalid minimum width: %u\n", min_width);
599 	}
600 
601 	value = HORIZONTAL_TAPS_5 | VERTICAL_TAPS_5;
602 	tegra_plane_writel(p, value, DC_WIN_WINDOWGROUP_SET_CONTROL_INPUT_SCALER);
603 
604 	if (new_state->src_w != new_state->crtc_w << 16) {
605 		fixed20_12 width = dfixed_init(new_state->src_w >> 16);
606 		u32 incr = compute_phase_incr(width, new_state->crtc_w) & ~0x1;
607 		u32 init = (1 << (NFB - 1)) + (incr >> 1);
608 
609 		tegra_plane_writel(p, incr, DC_WIN_SET_INPUT_SCALER_HPHASE_INCR);
610 		tegra_plane_writel(p, init, DC_WIN_SET_INPUT_SCALER_H_START_PHASE);
611 	} else {
612 		bypass |= INPUT_SCALER_HBYPASS;
613 	}
614 
615 	if (new_state->src_h != new_state->crtc_h << 16) {
616 		fixed20_12 height = dfixed_init(new_state->src_h >> 16);
617 		u32 incr = compute_phase_incr(height, new_state->crtc_h) & ~0x1;
618 		u32 init = (1 << (NFB - 1)) + (incr >> 1);
619 
620 		tegra_plane_writel(p, incr, DC_WIN_SET_INPUT_SCALER_VPHASE_INCR);
621 		tegra_plane_writel(p, init, DC_WIN_SET_INPUT_SCALER_V_START_PHASE);
622 	} else {
623 		bypass |= INPUT_SCALER_VBYPASS;
624 	}
625 
626 	tegra_plane_writel(p, bypass, DC_WIN_WINDOWGROUP_SET_INPUT_SCALER_USAGE);
627 
628 	/* disable compression */
629 	tegra_plane_writel(p, 0, DC_WINBUF_CDE_CONTROL);
630 
631 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
632 	/*
633 	 * Physical address bit 39 in Tegra194 is used as a switch for special
634 	 * logic that swizzles the memory using either the legacy Tegra or the
635 	 * dGPU sector layout.
636 	 */
637 	if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU)
638 		addr_flag = BIT_ULL(39);
639 #endif
640 
641 	base = tegra_plane_state->iova[0] + fb->offsets[0];
642 	base |= addr_flag;
643 
644 	tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH);
645 	tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS);
646 
647 	value = V_POSITION(new_state->crtc_y) |
648 		H_POSITION(new_state->crtc_x);
649 	tegra_plane_writel(p, value, DC_WIN_POSITION);
650 
651 	value = V_SIZE(new_state->crtc_h) | H_SIZE(new_state->crtc_w);
652 	tegra_plane_writel(p, value, DC_WIN_SIZE);
653 
654 	value = WIN_ENABLE | COLOR_EXPAND;
655 	tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS);
656 
657 	value = V_SIZE(new_state->src_h >> 16) | H_SIZE(new_state->src_w >> 16);
658 	tegra_plane_writel(p, value, DC_WIN_CROPPED_SIZE);
659 
660 	tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI);
661 	tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR);
662 
663 	value = PITCH(fb->pitches[0]);
664 	tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE);
665 
666 	if (yuv && planes > 1) {
667 		base = tegra_plane_state->iova[1] + fb->offsets[1];
668 		base |= addr_flag;
669 
670 		tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_U);
671 		tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_U);
672 
673 		if (planes > 2) {
674 			base = tegra_plane_state->iova[2] + fb->offsets[2];
675 			base |= addr_flag;
676 
677 			tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_V);
678 			tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_V);
679 		}
680 
681 		value = PITCH_U(fb->pitches[1]);
682 
683 		if (planes > 2)
684 			value |= PITCH_V(fb->pitches[2]);
685 
686 		tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE_UV);
687 	} else {
688 		tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_U);
689 		tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_HI_U);
690 		tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_V);
691 		tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_HI_V);
692 		tegra_plane_writel(p, 0, DC_WIN_PLANAR_STORAGE_UV);
693 	}
694 
695 	value = CLAMP_BEFORE_BLEND | INPUT_RANGE_FULL;
696 
697 	if (yuv) {
698 		if (bpc < 12)
699 			value |= DEGAMMA_YUV8_10;
700 		else
701 			value |= DEGAMMA_YUV12;
702 
703 		/* XXX parameterize */
704 		value |= COLOR_SPACE_YUV_2020;
705 	} else {
706 		if (!tegra_plane_format_is_indexed(tegra_plane_state->format))
707 			value |= DEGAMMA_SRGB;
708 	}
709 
710 	tegra_plane_writel(p, value, DC_WIN_SET_PARAMS);
711 
712 	value = OFFSET_X(new_state->src_y >> 16) |
713 		OFFSET_Y(new_state->src_x >> 16);
714 	tegra_plane_writel(p, value, DC_WINBUF_CROPPED_POINT);
715 
716 	if (dc->soc->supports_block_linear) {
717 		unsigned long height = tegra_plane_state->tiling.value;
718 
719 		/* XXX */
720 		switch (tegra_plane_state->tiling.mode) {
721 		case TEGRA_BO_TILING_MODE_PITCH:
722 			value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(0) |
723 				DC_WINBUF_SURFACE_KIND_PITCH;
724 			break;
725 
726 		/* XXX not supported on Tegra186 and later */
727 		case TEGRA_BO_TILING_MODE_TILED:
728 			value = DC_WINBUF_SURFACE_KIND_TILED;
729 			break;
730 
731 		case TEGRA_BO_TILING_MODE_BLOCK:
732 			value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
733 				DC_WINBUF_SURFACE_KIND_BLOCK;
734 			break;
735 		}
736 
737 		tegra_plane_writel(p, value, DC_WINBUF_SURFACE_KIND);
738 	}
739 
740 	/* disable gamut CSC */
741 	value = tegra_plane_readl(p, DC_WIN_WINDOW_SET_CONTROL);
742 	value &= ~CONTROL_CSC_ENABLE;
743 	tegra_plane_writel(p, value, DC_WIN_WINDOW_SET_CONTROL);
744 
745 	host1x_client_suspend(&dc->client);
746 }
747 
748 static const struct drm_plane_helper_funcs tegra_shared_plane_helper_funcs = {
749 	.prepare_fb = tegra_plane_prepare_fb,
750 	.cleanup_fb = tegra_plane_cleanup_fb,
751 	.atomic_check = tegra_shared_plane_atomic_check,
752 	.atomic_update = tegra_shared_plane_atomic_update,
753 	.atomic_disable = tegra_shared_plane_atomic_disable,
754 };
755 
tegra_shared_plane_create(struct drm_device * drm,struct tegra_dc * dc,unsigned int wgrp,unsigned int index)756 struct drm_plane *tegra_shared_plane_create(struct drm_device *drm,
757 					    struct tegra_dc *dc,
758 					    unsigned int wgrp,
759 					    unsigned int index)
760 {
761 	enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
762 	struct tegra_drm *tegra = drm->dev_private;
763 	struct tegra_display_hub *hub = tegra->hub;
764 	struct tegra_shared_plane *plane;
765 	unsigned int possible_crtcs;
766 	unsigned int num_formats;
767 	const u64 *modifiers;
768 	struct drm_plane *p;
769 	const u32 *formats;
770 	int err;
771 
772 	plane = kzalloc(sizeof(*plane), GFP_KERNEL);
773 	if (!plane)
774 		return ERR_PTR(-ENOMEM);
775 
776 	plane->base.offset = 0x0a00 + 0x0300 * index;
777 	plane->base.index = index;
778 
779 	plane->wgrp = &hub->wgrps[wgrp];
780 	plane->wgrp->parent = &dc->client;
781 
782 	p = &plane->base.base;
783 
784 	/* planes can be assigned to arbitrary CRTCs */
785 	possible_crtcs = BIT(tegra->num_crtcs) - 1;
786 
787 	num_formats = ARRAY_SIZE(tegra_shared_plane_formats);
788 	formats = tegra_shared_plane_formats;
789 	modifiers = tegra_shared_plane_modifiers;
790 
791 	err = drm_universal_plane_init(drm, p, possible_crtcs,
792 				       &tegra_plane_funcs, formats,
793 				       num_formats, modifiers, type, NULL);
794 	if (err < 0) {
795 		kfree(plane);
796 		return ERR_PTR(err);
797 	}
798 
799 	drm_plane_helper_add(p, &tegra_shared_plane_helper_funcs);
800 	drm_plane_create_zpos_property(p, 0, 0, 255);
801 
802 	return p;
803 }
804 
805 static struct drm_private_state *
tegra_display_hub_duplicate_state(struct drm_private_obj * obj)806 tegra_display_hub_duplicate_state(struct drm_private_obj *obj)
807 {
808 	struct tegra_display_hub_state *state;
809 
810 	state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL);
811 	if (!state)
812 		return NULL;
813 
814 	__drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
815 
816 	return &state->base;
817 }
818 
tegra_display_hub_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)819 static void tegra_display_hub_destroy_state(struct drm_private_obj *obj,
820 					    struct drm_private_state *state)
821 {
822 	struct tegra_display_hub_state *hub_state =
823 		to_tegra_display_hub_state(state);
824 
825 	kfree(hub_state);
826 }
827 
828 static const struct drm_private_state_funcs tegra_display_hub_state_funcs = {
829 	.atomic_duplicate_state = tegra_display_hub_duplicate_state,
830 	.atomic_destroy_state = tegra_display_hub_destroy_state,
831 };
832 
833 static struct tegra_display_hub_state *
tegra_display_hub_get_state(struct tegra_display_hub * hub,struct drm_atomic_state * state)834 tegra_display_hub_get_state(struct tegra_display_hub *hub,
835 			    struct drm_atomic_state *state)
836 {
837 	struct drm_private_state *priv;
838 
839 	priv = drm_atomic_get_private_obj_state(state, &hub->base);
840 	if (IS_ERR(priv))
841 		return ERR_CAST(priv);
842 
843 	return to_tegra_display_hub_state(priv);
844 }
845 
tegra_display_hub_atomic_check(struct drm_device * drm,struct drm_atomic_state * state)846 int tegra_display_hub_atomic_check(struct drm_device *drm,
847 				   struct drm_atomic_state *state)
848 {
849 	struct tegra_drm *tegra = drm->dev_private;
850 	struct tegra_display_hub_state *hub_state;
851 	struct drm_crtc_state *old, *new;
852 	struct drm_crtc *crtc;
853 	unsigned int i;
854 
855 	if (!tegra->hub)
856 		return 0;
857 
858 	hub_state = tegra_display_hub_get_state(tegra->hub, state);
859 	if (IS_ERR(hub_state))
860 		return PTR_ERR(hub_state);
861 
862 	/*
863 	 * The display hub display clock needs to be fed by the display clock
864 	 * with the highest frequency to ensure proper functioning of all the
865 	 * displays.
866 	 *
867 	 * Note that this isn't used before Tegra186, but it doesn't hurt and
868 	 * conditionalizing it would make the code less clean.
869 	 */
870 	for_each_oldnew_crtc_in_state(state, crtc, old, new, i) {
871 		struct tegra_dc_state *dc = to_dc_state(new);
872 
873 		if (new->active) {
874 			if (!hub_state->clk || dc->pclk > hub_state->rate) {
875 				hub_state->dc = to_tegra_dc(dc->base.crtc);
876 				hub_state->clk = hub_state->dc->clk;
877 				hub_state->rate = dc->pclk;
878 			}
879 		}
880 	}
881 
882 	return 0;
883 }
884 
tegra_display_hub_update(struct tegra_dc * dc)885 static void tegra_display_hub_update(struct tegra_dc *dc)
886 {
887 	u32 value;
888 	int err;
889 
890 	err = host1x_client_resume(&dc->client);
891 	if (err < 0) {
892 		dev_err(dc->dev, "failed to resume: %d\n", err);
893 		return;
894 	}
895 
896 	value = tegra_dc_readl(dc, DC_CMD_IHUB_COMMON_MISC_CTL);
897 	value &= ~LATENCY_EVENT;
898 	tegra_dc_writel(dc, value, DC_CMD_IHUB_COMMON_MISC_CTL);
899 
900 	value = tegra_dc_readl(dc, DC_DISP_IHUB_COMMON_DISPLAY_FETCH_METER);
901 	value = CURS_SLOTS(1) | WGRP_SLOTS(1);
902 	tegra_dc_writel(dc, value, DC_DISP_IHUB_COMMON_DISPLAY_FETCH_METER);
903 
904 	tegra_dc_writel(dc, COMMON_UPDATE, DC_CMD_STATE_CONTROL);
905 	tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
906 	tegra_dc_writel(dc, COMMON_ACTREQ, DC_CMD_STATE_CONTROL);
907 	tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
908 
909 	host1x_client_suspend(&dc->client);
910 }
911 
tegra_display_hub_atomic_commit(struct drm_device * drm,struct drm_atomic_state * state)912 void tegra_display_hub_atomic_commit(struct drm_device *drm,
913 				     struct drm_atomic_state *state)
914 {
915 	struct tegra_drm *tegra = drm->dev_private;
916 	struct tegra_display_hub *hub = tegra->hub;
917 	struct tegra_display_hub_state *hub_state;
918 	struct device *dev = hub->client.dev;
919 	int err;
920 
921 	hub_state = to_tegra_display_hub_state(hub->base.state);
922 
923 	if (hub_state->clk) {
924 		err = clk_set_rate(hub_state->clk, hub_state->rate);
925 		if (err < 0)
926 			dev_err(dev, "failed to set rate of %pC to %lu Hz\n",
927 				hub_state->clk, hub_state->rate);
928 
929 		err = clk_set_parent(hub->clk_disp, hub_state->clk);
930 		if (err < 0)
931 			dev_err(dev, "failed to set parent of %pC to %pC: %d\n",
932 				hub->clk_disp, hub_state->clk, err);
933 	}
934 
935 	if (hub_state->dc)
936 		tegra_display_hub_update(hub_state->dc);
937 }
938 
tegra_display_hub_init(struct host1x_client * client)939 static int tegra_display_hub_init(struct host1x_client *client)
940 {
941 	struct tegra_display_hub *hub = to_tegra_display_hub(client);
942 	struct drm_device *drm = dev_get_drvdata(client->host);
943 	struct tegra_drm *tegra = drm->dev_private;
944 	struct tegra_display_hub_state *state;
945 
946 	state = kzalloc(sizeof(*state), GFP_KERNEL);
947 	if (!state)
948 		return -ENOMEM;
949 
950 	drm_atomic_private_obj_init(drm, &hub->base, &state->base,
951 				    &tegra_display_hub_state_funcs);
952 
953 	tegra->hub = hub;
954 
955 	return 0;
956 }
957 
tegra_display_hub_exit(struct host1x_client * client)958 static int tegra_display_hub_exit(struct host1x_client *client)
959 {
960 	struct drm_device *drm = dev_get_drvdata(client->host);
961 	struct tegra_drm *tegra = drm->dev_private;
962 
963 	drm_atomic_private_obj_fini(&tegra->hub->base);
964 	tegra->hub = NULL;
965 
966 	return 0;
967 }
968 
tegra_display_hub_runtime_suspend(struct host1x_client * client)969 static int tegra_display_hub_runtime_suspend(struct host1x_client *client)
970 {
971 	struct tegra_display_hub *hub = to_tegra_display_hub(client);
972 	struct device *dev = client->dev;
973 	unsigned int i = hub->num_heads;
974 	int err;
975 
976 	err = reset_control_assert(hub->rst);
977 	if (err < 0)
978 		return err;
979 
980 	while (i--)
981 		clk_disable_unprepare(hub->clk_heads[i]);
982 
983 	clk_disable_unprepare(hub->clk_hub);
984 	clk_disable_unprepare(hub->clk_dsc);
985 	clk_disable_unprepare(hub->clk_disp);
986 
987 	pm_runtime_put_sync(dev);
988 
989 	return 0;
990 }
991 
tegra_display_hub_runtime_resume(struct host1x_client * client)992 static int tegra_display_hub_runtime_resume(struct host1x_client *client)
993 {
994 	struct tegra_display_hub *hub = to_tegra_display_hub(client);
995 	struct device *dev = client->dev;
996 	unsigned int i;
997 	int err;
998 
999 	err = pm_runtime_resume_and_get(dev);
1000 	if (err < 0) {
1001 		dev_err(dev, "failed to get runtime PM: %d\n", err);
1002 		return err;
1003 	}
1004 
1005 	err = clk_prepare_enable(hub->clk_disp);
1006 	if (err < 0)
1007 		goto put_rpm;
1008 
1009 	err = clk_prepare_enable(hub->clk_dsc);
1010 	if (err < 0)
1011 		goto disable_disp;
1012 
1013 	err = clk_prepare_enable(hub->clk_hub);
1014 	if (err < 0)
1015 		goto disable_dsc;
1016 
1017 	for (i = 0; i < hub->num_heads; i++) {
1018 		err = clk_prepare_enable(hub->clk_heads[i]);
1019 		if (err < 0)
1020 			goto disable_heads;
1021 	}
1022 
1023 	err = reset_control_deassert(hub->rst);
1024 	if (err < 0)
1025 		goto disable_heads;
1026 
1027 	return 0;
1028 
1029 disable_heads:
1030 	while (i--)
1031 		clk_disable_unprepare(hub->clk_heads[i]);
1032 
1033 	clk_disable_unprepare(hub->clk_hub);
1034 disable_dsc:
1035 	clk_disable_unprepare(hub->clk_dsc);
1036 disable_disp:
1037 	clk_disable_unprepare(hub->clk_disp);
1038 put_rpm:
1039 	pm_runtime_put_sync(dev);
1040 	return err;
1041 }
1042 
1043 static const struct host1x_client_ops tegra_display_hub_ops = {
1044 	.init = tegra_display_hub_init,
1045 	.exit = tegra_display_hub_exit,
1046 	.suspend = tegra_display_hub_runtime_suspend,
1047 	.resume = tegra_display_hub_runtime_resume,
1048 };
1049 
tegra_display_hub_probe(struct platform_device * pdev)1050 static int tegra_display_hub_probe(struct platform_device *pdev)
1051 {
1052 	u64 dma_mask = dma_get_mask(pdev->dev.parent);
1053 	struct device_node *child = NULL;
1054 	struct tegra_display_hub *hub;
1055 	struct clk *clk;
1056 	unsigned int i;
1057 	int err;
1058 
1059 	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
1060 	if (err < 0) {
1061 		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
1062 		return err;
1063 	}
1064 
1065 	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);
1066 	if (!hub)
1067 		return -ENOMEM;
1068 
1069 	hub->soc = of_device_get_match_data(&pdev->dev);
1070 
1071 	hub->clk_disp = devm_clk_get(&pdev->dev, "disp");
1072 	if (IS_ERR(hub->clk_disp)) {
1073 		err = PTR_ERR(hub->clk_disp);
1074 		return err;
1075 	}
1076 
1077 	if (hub->soc->supports_dsc) {
1078 		hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
1079 		if (IS_ERR(hub->clk_dsc)) {
1080 			err = PTR_ERR(hub->clk_dsc);
1081 			return err;
1082 		}
1083 	}
1084 
1085 	hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
1086 	if (IS_ERR(hub->clk_hub)) {
1087 		err = PTR_ERR(hub->clk_hub);
1088 		return err;
1089 	}
1090 
1091 	hub->rst = devm_reset_control_get(&pdev->dev, "misc");
1092 	if (IS_ERR(hub->rst)) {
1093 		err = PTR_ERR(hub->rst);
1094 		return err;
1095 	}
1096 
1097 	hub->wgrps = devm_kcalloc(&pdev->dev, hub->soc->num_wgrps,
1098 				  sizeof(*hub->wgrps), GFP_KERNEL);
1099 	if (!hub->wgrps)
1100 		return -ENOMEM;
1101 
1102 	for (i = 0; i < hub->soc->num_wgrps; i++) {
1103 		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
1104 		char id[8];
1105 
1106 		snprintf(id, sizeof(id), "wgrp%u", i);
1107 		mutex_init(&wgrp->lock);
1108 		wgrp->usecount = 0;
1109 		wgrp->index = i;
1110 
1111 		wgrp->rst = devm_reset_control_get(&pdev->dev, id);
1112 		if (IS_ERR(wgrp->rst))
1113 			return PTR_ERR(wgrp->rst);
1114 
1115 		err = reset_control_assert(wgrp->rst);
1116 		if (err < 0)
1117 			return err;
1118 	}
1119 
1120 	hub->num_heads = of_get_child_count(pdev->dev.of_node);
1121 
1122 	hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk),
1123 				      GFP_KERNEL);
1124 	if (!hub->clk_heads)
1125 		return -ENOMEM;
1126 
1127 	for (i = 0; i < hub->num_heads; i++) {
1128 		child = of_get_next_child(pdev->dev.of_node, child);
1129 		if (!child) {
1130 			dev_err(&pdev->dev, "failed to find node for head %u\n",
1131 				i);
1132 			return -ENODEV;
1133 		}
1134 
1135 		clk = devm_get_clk_from_child(&pdev->dev, child, "dc");
1136 		if (IS_ERR(clk)) {
1137 			dev_err(&pdev->dev, "failed to get clock for head %u\n",
1138 				i);
1139 			of_node_put(child);
1140 			return PTR_ERR(clk);
1141 		}
1142 
1143 		hub->clk_heads[i] = clk;
1144 	}
1145 
1146 	of_node_put(child);
1147 
1148 	/* XXX: enable clock across reset? */
1149 	err = reset_control_assert(hub->rst);
1150 	if (err < 0)
1151 		return err;
1152 
1153 	platform_set_drvdata(pdev, hub);
1154 	pm_runtime_enable(&pdev->dev);
1155 
1156 	INIT_LIST_HEAD(&hub->client.list);
1157 	hub->client.ops = &tegra_display_hub_ops;
1158 	hub->client.dev = &pdev->dev;
1159 
1160 	err = host1x_client_register(&hub->client);
1161 	if (err < 0)
1162 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1163 			err);
1164 
1165 	err = devm_of_platform_populate(&pdev->dev);
1166 	if (err < 0)
1167 		goto unregister;
1168 
1169 	return err;
1170 
1171 unregister:
1172 	host1x_client_unregister(&hub->client);
1173 	pm_runtime_disable(&pdev->dev);
1174 	return err;
1175 }
1176 
tegra_display_hub_remove(struct platform_device * pdev)1177 static void tegra_display_hub_remove(struct platform_device *pdev)
1178 {
1179 	struct tegra_display_hub *hub = platform_get_drvdata(pdev);
1180 	unsigned int i;
1181 
1182 	host1x_client_unregister(&hub->client);
1183 
1184 	for (i = 0; i < hub->soc->num_wgrps; i++) {
1185 		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
1186 
1187 		mutex_destroy(&wgrp->lock);
1188 	}
1189 
1190 	pm_runtime_disable(&pdev->dev);
1191 }
1192 
1193 static const struct tegra_display_hub_soc tegra186_display_hub = {
1194 	.num_wgrps = 6,
1195 	.supports_dsc = true,
1196 };
1197 
1198 static const struct tegra_display_hub_soc tegra194_display_hub = {
1199 	.num_wgrps = 6,
1200 	.supports_dsc = false,
1201 };
1202 
1203 static const struct of_device_id tegra_display_hub_of_match[] = {
1204 	{
1205 		.compatible = "nvidia,tegra194-display",
1206 		.data = &tegra194_display_hub
1207 	}, {
1208 		.compatible = "nvidia,tegra186-display",
1209 		.data = &tegra186_display_hub
1210 	}, {
1211 		/* sentinel */
1212 	}
1213 };
1214 MODULE_DEVICE_TABLE(of, tegra_display_hub_of_match);
1215 
1216 struct platform_driver tegra_display_hub_driver = {
1217 	.driver = {
1218 		.name = "tegra-display-hub",
1219 		.of_match_table = tegra_display_hub_of_match,
1220 	},
1221 	.probe = tegra_display_hub_probe,
1222 	.remove_new = tegra_display_hub_remove,
1223 };
1224