xref: /linux/drivers/gpu/drm/tegra/hub.c (revision e70140ba0d2b1a30467d4af6bcfe761327b9ec95)
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;
525 
526 	tmp = (u64)dfixed_trunc(in);
527 	tmp1 = (tmp << NFB) + ((u64)out >> 1);
528 	do_div(tmp1, out);
529 
530 	return lower_32_bits(tmp1);
531 }
532 
tegra_shared_plane_atomic_update(struct drm_plane * plane,struct drm_atomic_state * state)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 
tegra_shared_plane_create(struct drm_device * drm,struct tegra_dc * dc,unsigned int wgrp,unsigned int index)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 *
tegra_display_hub_duplicate_state(struct drm_private_obj * obj)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 
tegra_display_hub_destroy_state(struct drm_private_obj * obj,struct drm_private_state * state)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 *
tegra_display_hub_get_state(struct tegra_display_hub * hub,struct drm_atomic_state * 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 
tegra_display_hub_atomic_check(struct drm_device * drm,struct drm_atomic_state * state)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 
tegra_display_hub_update(struct tegra_dc * dc)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 
tegra_display_hub_atomic_commit(struct drm_device * drm,struct drm_atomic_state * state)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 
tegra_display_hub_init(struct host1x_client * client)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 
tegra_display_hub_exit(struct host1x_client * client)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 
tegra_display_hub_runtime_suspend(struct host1x_client * client)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 
tegra_display_hub_runtime_resume(struct host1x_client * client)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 
tegra_display_hub_probe(struct platform_device * pdev)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[16];
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 
tegra_display_hub_remove(struct platform_device * pdev)1176 static void tegra_display_hub_remove(struct platform_device *pdev)
1177 {
1178 	struct tegra_display_hub *hub = platform_get_drvdata(pdev);
1179 	unsigned int i;
1180 
1181 	host1x_client_unregister(&hub->client);
1182 
1183 	for (i = 0; i < hub->soc->num_wgrps; i++) {
1184 		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
1185 
1186 		mutex_destroy(&wgrp->lock);
1187 	}
1188 
1189 	pm_runtime_disable(&pdev->dev);
1190 }
1191 
1192 static const struct tegra_display_hub_soc tegra186_display_hub = {
1193 	.num_wgrps = 6,
1194 	.supports_dsc = true,
1195 };
1196 
1197 static const struct tegra_display_hub_soc tegra194_display_hub = {
1198 	.num_wgrps = 6,
1199 	.supports_dsc = false,
1200 };
1201 
1202 static const struct of_device_id tegra_display_hub_of_match[] = {
1203 	{
1204 		.compatible = "nvidia,tegra194-display",
1205 		.data = &tegra194_display_hub
1206 	}, {
1207 		.compatible = "nvidia,tegra186-display",
1208 		.data = &tegra186_display_hub
1209 	}, {
1210 		/* sentinel */
1211 	}
1212 };
1213 MODULE_DEVICE_TABLE(of, tegra_display_hub_of_match);
1214 
1215 struct platform_driver tegra_display_hub_driver = {
1216 	.driver = {
1217 		.name = "tegra-display-hub",
1218 		.of_match_table = tegra_display_hub_of_match,
1219 	},
1220 	.probe = tegra_display_hub_probe,
1221 	.remove = tegra_display_hub_remove,
1222 };
1223