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