brintos

brintos / linux-shallow public Read only

0
0
Text · 90.1 KiB · be61c9d Raw
3291 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2012 Avionic Design GmbH4 * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.5 */6 7#include <linux/clk.h>8#include <linux/debugfs.h>9#include <linux/delay.h>10#include <linux/dma-mapping.h>11#include <linux/iommu.h>12#include <linux/interconnect.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/platform_device.h>16#include <linux/pm_domain.h>17#include <linux/pm_opp.h>18#include <linux/pm_runtime.h>19#include <linux/reset.h>20 21#include <soc/tegra/common.h>22#include <soc/tegra/pmc.h>23 24#include <drm/drm_atomic.h>25#include <drm/drm_atomic_helper.h>26#include <drm/drm_blend.h>27#include <drm/drm_debugfs.h>28#include <drm/drm_fourcc.h>29#include <drm/drm_framebuffer.h>30#include <drm/drm_vblank.h>31 32#include "dc.h"33#include "drm.h"34#include "gem.h"35#include "hub.h"36#include "plane.h"37 38static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,39					    struct drm_crtc_state *state);40 41static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)42{43	stats->frames = 0;44	stats->vblank = 0;45	stats->underflow = 0;46	stats->overflow = 0;47}48 49/* Reads the active copy of a register. */50static u32 tegra_dc_readl_active(struct tegra_dc *dc, unsigned long offset)51{52	u32 value;53 54	tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);55	value = tegra_dc_readl(dc, offset);56	tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);57 58	return value;59}60 61static inline unsigned int tegra_plane_offset(struct tegra_plane *plane,62					      unsigned int offset)63{64	if (offset >= 0x500 && offset <= 0x638) {65		offset = 0x000 + (offset - 0x500);66		return plane->offset + offset;67	}68 69	if (offset >= 0x700 && offset <= 0x719) {70		offset = 0x180 + (offset - 0x700);71		return plane->offset + offset;72	}73 74	if (offset >= 0x800 && offset <= 0x839) {75		offset = 0x1c0 + (offset - 0x800);76		return plane->offset + offset;77	}78 79	dev_WARN(plane->dc->dev, "invalid offset: %x\n", offset);80 81	return plane->offset + offset;82}83 84static inline u32 tegra_plane_readl(struct tegra_plane *plane,85				    unsigned int offset)86{87	return tegra_dc_readl(plane->dc, tegra_plane_offset(plane, offset));88}89 90static inline void tegra_plane_writel(struct tegra_plane *plane, u32 value,91				      unsigned int offset)92{93	tegra_dc_writel(plane->dc, value, tegra_plane_offset(plane, offset));94}95 96bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev)97{98	struct device_node *np = dc->dev->of_node;99	struct of_phandle_iterator it;100	int err;101 102	of_for_each_phandle(&it, err, np, "nvidia,outputs", NULL, 0)103		if (it.node == dev->of_node)104			return true;105 106	return false;107}108 109/*110 * Double-buffered registers have two copies: ASSEMBLY and ACTIVE. When the111 * *_ACT_REQ bits are set the ASSEMBLY copy is latched into the ACTIVE copy.112 * Latching happens mmediately if the display controller is in STOP mode or113 * on the next frame boundary otherwise.114 *115 * Triple-buffered registers have three copies: ASSEMBLY, ARM and ACTIVE. The116 * ASSEMBLY copy is latched into the ARM copy immediately after *_UPDATE bits117 * are written. When the *_ACT_REQ bits are written, the ARM copy is latched118 * into the ACTIVE copy, either immediately if the display controller is in119 * STOP mode, or at the next frame boundary otherwise.120 */121void tegra_dc_commit(struct tegra_dc *dc)122{123	tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);124	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);125}126 127static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,128				  unsigned int bpp)129{130	fixed20_12 outf = dfixed_init(out);131	fixed20_12 inf = dfixed_init(in);132	u32 dda_inc;133	int max;134 135	if (v)136		max = 15;137	else {138		switch (bpp) {139		case 2:140			max = 8;141			break;142 143		default:144			WARN_ON_ONCE(1);145			fallthrough;146		case 4:147			max = 4;148			break;149		}150	}151 152	outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));153	inf.full -= dfixed_const(1);154 155	dda_inc = dfixed_div(inf, outf);156	dda_inc = min_t(u32, dda_inc, dfixed_const(max));157 158	return dda_inc;159}160 161static inline u32 compute_initial_dda(unsigned int in)162{163	fixed20_12 inf = dfixed_init(in);164	return dfixed_frac(inf);165}166 167static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane)168{169	u32 background[3] = {170		BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,171		BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,172		BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE,173	};174	u32 foreground = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255) |175			 BLEND_COLOR_KEY_NONE;176	u32 blendnokey = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255);177	struct tegra_plane_state *state;178	u32 blending[2];179	unsigned int i;180 181	/* disable blending for non-overlapping case */182	tegra_plane_writel(plane, blendnokey, DC_WIN_BLEND_NOKEY);183	tegra_plane_writel(plane, foreground, DC_WIN_BLEND_1WIN);184 185	state = to_tegra_plane_state(plane->base.state);186 187	if (state->opaque) {188		/*189		 * Since custom fix-weight blending isn't utilized and weight190		 * of top window is set to max, we can enforce dependent191		 * blending which in this case results in transparent bottom192		 * window if top window is opaque and if top window enables193		 * alpha blending, then bottom window is getting alpha value194		 * of 1 minus the sum of alpha components of the overlapping195		 * plane.196		 */197		background[0] |= BLEND_CONTROL_DEPENDENT;198		background[1] |= BLEND_CONTROL_DEPENDENT;199 200		/*201		 * The region where three windows overlap is the intersection202		 * of the two regions where two windows overlap. It contributes203		 * to the area if all of the windows on top of it have an alpha204		 * component.205		 */206		switch (state->base.normalized_zpos) {207		case 0:208			if (state->blending[0].alpha &&209			    state->blending[1].alpha)210				background[2] |= BLEND_CONTROL_DEPENDENT;211			break;212 213		case 1:214			background[2] |= BLEND_CONTROL_DEPENDENT;215			break;216		}217	} else {218		/*219		 * Enable alpha blending if pixel format has an alpha220		 * component.221		 */222		foreground |= BLEND_CONTROL_ALPHA;223 224		/*225		 * If any of the windows on top of this window is opaque, it226		 * will completely conceal this window within that area. If227		 * top window has an alpha component, it is blended over the228		 * bottom window.229		 */230		for (i = 0; i < 2; i++) {231			if (state->blending[i].alpha &&232			    state->blending[i].top)233				background[i] |= BLEND_CONTROL_DEPENDENT;234		}235 236		switch (state->base.normalized_zpos) {237		case 0:238			if (state->blending[0].alpha &&239			    state->blending[1].alpha)240				background[2] |= BLEND_CONTROL_DEPENDENT;241			break;242 243		case 1:244			/*245			 * When both middle and topmost windows have an alpha,246			 * these windows a mixed together and then the result247			 * is blended over the bottom window.248			 */249			if (state->blending[0].alpha &&250			    state->blending[0].top)251				background[2] |= BLEND_CONTROL_ALPHA;252 253			if (state->blending[1].alpha &&254			    state->blending[1].top)255				background[2] |= BLEND_CONTROL_ALPHA;256			break;257		}258	}259 260	switch (state->base.normalized_zpos) {261	case 0:262		tegra_plane_writel(plane, background[0], DC_WIN_BLEND_2WIN_X);263		tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y);264		tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY);265		break;266 267	case 1:268		/*269		 * If window B / C is topmost, then X / Y registers are270		 * matching the order of blending[...] state indices,271		 * otherwise a swap is required.272		 */273		if (!state->blending[0].top && state->blending[1].top) {274			blending[0] = foreground;275			blending[1] = background[1];276		} else {277			blending[0] = background[0];278			blending[1] = foreground;279		}280 281		tegra_plane_writel(plane, blending[0], DC_WIN_BLEND_2WIN_X);282		tegra_plane_writel(plane, blending[1], DC_WIN_BLEND_2WIN_Y);283		tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY);284		break;285 286	case 2:287		tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X);288		tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_Y);289		tegra_plane_writel(plane, foreground, DC_WIN_BLEND_3WIN_XY);290		break;291	}292}293 294static void tegra_plane_setup_blending(struct tegra_plane *plane,295				       const struct tegra_dc_window *window)296{297	u32 value;298 299	value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 |300		BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC |301		BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC;302	tegra_plane_writel(plane, value, DC_WIN_BLEND_MATCH_SELECT);303 304	value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 |305		BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC |306		BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC;307	tegra_plane_writel(plane, value, DC_WIN_BLEND_NOMATCH_SELECT);308 309	value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - window->zpos);310	tegra_plane_writel(plane, value, DC_WIN_BLEND_LAYER_CONTROL);311}312 313static bool314tegra_plane_use_horizontal_filtering(struct tegra_plane *plane,315				     const struct tegra_dc_window *window)316{317	struct tegra_dc *dc = plane->dc;318 319	if (window->src.w == window->dst.w)320		return false;321 322	if (plane->index == 0 && dc->soc->has_win_a_without_filters)323		return false;324 325	return true;326}327 328static bool329tegra_plane_use_vertical_filtering(struct tegra_plane *plane,330				   const struct tegra_dc_window *window)331{332	struct tegra_dc *dc = plane->dc;333 334	if (window->src.h == window->dst.h)335		return false;336 337	if (plane->index == 0 && dc->soc->has_win_a_without_filters)338		return false;339 340	if (plane->index == 2 && dc->soc->has_win_c_without_vert_filter)341		return false;342 343	return true;344}345 346static void tegra_dc_setup_window(struct tegra_plane *plane,347				  const struct tegra_dc_window *window)348{349	unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;350	struct tegra_dc *dc = plane->dc;351	unsigned int planes;352	u32 value;353	bool yuv;354 355	/*356	 * For YUV planar modes, the number of bytes per pixel takes into357	 * account only the luma component and therefore is 1.358	 */359	yuv = tegra_plane_format_is_yuv(window->format, &planes, NULL);360	if (!yuv)361		bpp = window->bits_per_pixel / 8;362	else363		bpp = (planes > 1) ? 1 : 2;364 365	tegra_plane_writel(plane, window->format, DC_WIN_COLOR_DEPTH);366	tegra_plane_writel(plane, window->swap, DC_WIN_BYTE_SWAP);367 368	value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);369	tegra_plane_writel(plane, value, DC_WIN_POSITION);370 371	value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);372	tegra_plane_writel(plane, value, DC_WIN_SIZE);373 374	h_offset = window->src.x * bpp;375	v_offset = window->src.y;376	h_size = window->src.w * bpp;377	v_size = window->src.h;378 379	if (window->reflect_x)380		h_offset += (window->src.w - 1) * bpp;381 382	if (window->reflect_y)383		v_offset += window->src.h - 1;384 385	value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);386	tegra_plane_writel(plane, value, DC_WIN_PRESCALED_SIZE);387 388	/*389	 * For DDA computations the number of bytes per pixel for YUV planar390	 * modes needs to take into account all Y, U and V components.391	 */392	if (yuv && planes > 1)393		bpp = 2;394 395	h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);396	v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);397 398	value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);399	tegra_plane_writel(plane, value, DC_WIN_DDA_INC);400 401	h_dda = compute_initial_dda(window->src.x);402	v_dda = compute_initial_dda(window->src.y);403 404	tegra_plane_writel(plane, h_dda, DC_WIN_H_INITIAL_DDA);405	tegra_plane_writel(plane, v_dda, DC_WIN_V_INITIAL_DDA);406 407	tegra_plane_writel(plane, 0, DC_WIN_UV_BUF_STRIDE);408	tegra_plane_writel(plane, 0, DC_WIN_BUF_STRIDE);409 410	tegra_plane_writel(plane, window->base[0], DC_WINBUF_START_ADDR);411 412	if (yuv && planes > 1) {413		tegra_plane_writel(plane, window->base[1], DC_WINBUF_START_ADDR_U);414 415		if (planes > 2)416			tegra_plane_writel(plane, window->base[2], DC_WINBUF_START_ADDR_V);417 418		value = window->stride[1] << 16 | window->stride[0];419		tegra_plane_writel(plane, value, DC_WIN_LINE_STRIDE);420	} else {421		tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE);422	}423 424	tegra_plane_writel(plane, h_offset, DC_WINBUF_ADDR_H_OFFSET);425	tegra_plane_writel(plane, v_offset, DC_WINBUF_ADDR_V_OFFSET);426 427	if (dc->soc->supports_block_linear) {428		unsigned long height = window->tiling.value;429 430		switch (window->tiling.mode) {431		case TEGRA_BO_TILING_MODE_PITCH:432			value = DC_WINBUF_SURFACE_KIND_PITCH;433			break;434 435		case TEGRA_BO_TILING_MODE_TILED:436			value = DC_WINBUF_SURFACE_KIND_TILED;437			break;438 439		case TEGRA_BO_TILING_MODE_BLOCK:440			value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |441				DC_WINBUF_SURFACE_KIND_BLOCK;442			break;443		}444 445		tegra_plane_writel(plane, value, DC_WINBUF_SURFACE_KIND);446	} else {447		switch (window->tiling.mode) {448		case TEGRA_BO_TILING_MODE_PITCH:449			value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |450				DC_WIN_BUFFER_ADDR_MODE_LINEAR;451			break;452 453		case TEGRA_BO_TILING_MODE_TILED:454			value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |455				DC_WIN_BUFFER_ADDR_MODE_TILE;456			break;457 458		case TEGRA_BO_TILING_MODE_BLOCK:459			/*460			 * No need to handle this here because ->atomic_check461			 * will already have filtered it out.462			 */463			break;464		}465 466		tegra_plane_writel(plane, value, DC_WIN_BUFFER_ADDR_MODE);467	}468 469	value = WIN_ENABLE;470 471	if (yuv) {472		/* setup default colorspace conversion coefficients */473		tegra_plane_writel(plane, 0x00f0, DC_WIN_CSC_YOF);474		tegra_plane_writel(plane, 0x012a, DC_WIN_CSC_KYRGB);475		tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KUR);476		tegra_plane_writel(plane, 0x0198, DC_WIN_CSC_KVR);477		tegra_plane_writel(plane, 0x039b, DC_WIN_CSC_KUG);478		tegra_plane_writel(plane, 0x032f, DC_WIN_CSC_KVG);479		tegra_plane_writel(plane, 0x0204, DC_WIN_CSC_KUB);480		tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KVB);481 482		value |= CSC_ENABLE;483	} else if (window->bits_per_pixel < 24) {484		value |= COLOR_EXPAND;485	}486 487	if (window->reflect_x)488		value |= H_DIRECTION;489 490	if (window->reflect_y)491		value |= V_DIRECTION;492 493	if (tegra_plane_use_horizontal_filtering(plane, window)) {494		/*495		 * Enable horizontal 6-tap filter and set filtering496		 * coefficients to the default values defined in TRM.497		 */498		tegra_plane_writel(plane, 0x00008000, DC_WIN_H_FILTER_P(0));499		tegra_plane_writel(plane, 0x3e087ce1, DC_WIN_H_FILTER_P(1));500		tegra_plane_writel(plane, 0x3b117ac1, DC_WIN_H_FILTER_P(2));501		tegra_plane_writel(plane, 0x591b73aa, DC_WIN_H_FILTER_P(3));502		tegra_plane_writel(plane, 0x57256d9a, DC_WIN_H_FILTER_P(4));503		tegra_plane_writel(plane, 0x552f668b, DC_WIN_H_FILTER_P(5));504		tegra_plane_writel(plane, 0x73385e8b, DC_WIN_H_FILTER_P(6));505		tegra_plane_writel(plane, 0x72435583, DC_WIN_H_FILTER_P(7));506		tegra_plane_writel(plane, 0x714c4c8b, DC_WIN_H_FILTER_P(8));507		tegra_plane_writel(plane, 0x70554393, DC_WIN_H_FILTER_P(9));508		tegra_plane_writel(plane, 0x715e389b, DC_WIN_H_FILTER_P(10));509		tegra_plane_writel(plane, 0x71662faa, DC_WIN_H_FILTER_P(11));510		tegra_plane_writel(plane, 0x536d25ba, DC_WIN_H_FILTER_P(12));511		tegra_plane_writel(plane, 0x55731bca, DC_WIN_H_FILTER_P(13));512		tegra_plane_writel(plane, 0x387a11d9, DC_WIN_H_FILTER_P(14));513		tegra_plane_writel(plane, 0x3c7c08f1, DC_WIN_H_FILTER_P(15));514 515		value |= H_FILTER;516	}517 518	if (tegra_plane_use_vertical_filtering(plane, window)) {519		unsigned int i, k;520 521		/*522		 * Enable vertical 2-tap filter and set filtering523		 * coefficients to the default values defined in TRM.524		 */525		for (i = 0, k = 128; i < 16; i++, k -= 8)526			tegra_plane_writel(plane, k, DC_WIN_V_FILTER_P(i));527 528		value |= V_FILTER;529	}530 531	tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS);532 533	if (dc->soc->has_legacy_blending)534		tegra_plane_setup_blending_legacy(plane);535	else536		tegra_plane_setup_blending(plane, window);537}538 539static const u32 tegra20_primary_formats[] = {540	DRM_FORMAT_ARGB4444,541	DRM_FORMAT_ARGB1555,542	DRM_FORMAT_RGB565,543	DRM_FORMAT_RGBA5551,544	DRM_FORMAT_ABGR8888,545	DRM_FORMAT_ARGB8888,546	/* non-native formats */547	DRM_FORMAT_XRGB1555,548	DRM_FORMAT_RGBX5551,549	DRM_FORMAT_XBGR8888,550	DRM_FORMAT_XRGB8888,551};552 553static const u64 tegra20_modifiers[] = {554	DRM_FORMAT_MOD_LINEAR,555	DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED,556	DRM_FORMAT_MOD_INVALID557};558 559static const u32 tegra114_primary_formats[] = {560	DRM_FORMAT_ARGB4444,561	DRM_FORMAT_ARGB1555,562	DRM_FORMAT_RGB565,563	DRM_FORMAT_RGBA5551,564	DRM_FORMAT_ABGR8888,565	DRM_FORMAT_ARGB8888,566	/* new on Tegra114 */567	DRM_FORMAT_ABGR4444,568	DRM_FORMAT_ABGR1555,569	DRM_FORMAT_BGRA5551,570	DRM_FORMAT_XRGB1555,571	DRM_FORMAT_RGBX5551,572	DRM_FORMAT_XBGR1555,573	DRM_FORMAT_BGRX5551,574	DRM_FORMAT_BGR565,575	DRM_FORMAT_BGRA8888,576	DRM_FORMAT_RGBA8888,577	DRM_FORMAT_XRGB8888,578	DRM_FORMAT_XBGR8888,579};580 581static const u32 tegra124_primary_formats[] = {582	DRM_FORMAT_ARGB4444,583	DRM_FORMAT_ARGB1555,584	DRM_FORMAT_RGB565,585	DRM_FORMAT_RGBA5551,586	DRM_FORMAT_ABGR8888,587	DRM_FORMAT_ARGB8888,588	/* new on Tegra114 */589	DRM_FORMAT_ABGR4444,590	DRM_FORMAT_ABGR1555,591	DRM_FORMAT_BGRA5551,592	DRM_FORMAT_XRGB1555,593	DRM_FORMAT_RGBX5551,594	DRM_FORMAT_XBGR1555,595	DRM_FORMAT_BGRX5551,596	DRM_FORMAT_BGR565,597	DRM_FORMAT_BGRA8888,598	DRM_FORMAT_RGBA8888,599	DRM_FORMAT_XRGB8888,600	DRM_FORMAT_XBGR8888,601	/* new on Tegra124 */602	DRM_FORMAT_RGBX8888,603	DRM_FORMAT_BGRX8888,604};605 606static const u64 tegra124_modifiers[] = {607	DRM_FORMAT_MOD_LINEAR,608	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),609	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),610	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),611	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),612	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),613	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),614	DRM_FORMAT_MOD_INVALID615};616 617static int tegra_plane_atomic_check(struct drm_plane *plane,618				    struct drm_atomic_state *state)619{620	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,621										 plane);622	struct tegra_plane_state *plane_state = to_tegra_plane_state(new_plane_state);623	unsigned int supported_rotation = DRM_MODE_ROTATE_0 |624					  DRM_MODE_REFLECT_X |625					  DRM_MODE_REFLECT_Y;626	unsigned int rotation = new_plane_state->rotation;627	struct tegra_bo_tiling *tiling = &plane_state->tiling;628	struct tegra_plane *tegra = to_tegra_plane(plane);629	struct tegra_dc *dc = to_tegra_dc(new_plane_state->crtc);630	int err;631 632	plane_state->peak_memory_bandwidth = 0;633	plane_state->avg_memory_bandwidth = 0;634 635	/* no need for further checks if the plane is being disabled */636	if (!new_plane_state->crtc) {637		plane_state->total_peak_memory_bandwidth = 0;638		return 0;639	}640 641	err = tegra_plane_format(new_plane_state->fb->format->format,642				 &plane_state->format,643				 &plane_state->swap);644	if (err < 0)645		return err;646 647	/*648	 * Tegra20 and Tegra30 are special cases here because they support649	 * only variants of specific formats with an alpha component, but not650	 * the corresponding opaque formats. However, the opaque formats can651	 * be emulated by disabling alpha blending for the plane.652	 */653	if (dc->soc->has_legacy_blending) {654		err = tegra_plane_setup_legacy_state(tegra, plane_state);655		if (err < 0)656			return err;657	}658 659	err = tegra_fb_get_tiling(new_plane_state->fb, tiling);660	if (err < 0)661		return err;662 663	if (tiling->mode == TEGRA_BO_TILING_MODE_BLOCK &&664	    !dc->soc->supports_block_linear) {665		DRM_ERROR("hardware doesn't support block linear mode\n");666		return -EINVAL;667	}668 669	/*670	 * Older userspace used custom BO flag in order to specify the Y671	 * reflection, while modern userspace uses the generic DRM rotation672	 * property in order to achieve the same result.  The legacy BO flag673	 * duplicates the DRM rotation property when both are set.674	 */675	if (tegra_fb_is_bottom_up(new_plane_state->fb))676		rotation |= DRM_MODE_REFLECT_Y;677 678	rotation = drm_rotation_simplify(rotation, supported_rotation);679 680	if (rotation & DRM_MODE_REFLECT_X)681		plane_state->reflect_x = true;682	else683		plane_state->reflect_x = false;684 685	if (rotation & DRM_MODE_REFLECT_Y)686		plane_state->reflect_y = true;687	else688		plane_state->reflect_y = false;689 690	/*691	 * Tegra doesn't support different strides for U and V planes so we692	 * error out if the user tries to display a framebuffer with such a693	 * configuration.694	 */695	if (new_plane_state->fb->format->num_planes > 2) {696		if (new_plane_state->fb->pitches[2] != new_plane_state->fb->pitches[1]) {697			DRM_ERROR("unsupported UV-plane configuration\n");698			return -EINVAL;699		}700	}701 702	err = tegra_plane_state_add(tegra, new_plane_state);703	if (err < 0)704		return err;705 706	return 0;707}708 709static void tegra_plane_atomic_disable(struct drm_plane *plane,710				       struct drm_atomic_state *state)711{712	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,713									   plane);714	struct tegra_plane *p = to_tegra_plane(plane);715	u32 value;716 717	/* rien ne va plus */718	if (!old_state || !old_state->crtc)719		return;720 721	value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS);722	value &= ~WIN_ENABLE;723	tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS);724}725 726static void tegra_plane_atomic_update(struct drm_plane *plane,727				      struct drm_atomic_state *state)728{729	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,730									   plane);731	struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state);732	struct drm_framebuffer *fb = new_state->fb;733	struct tegra_plane *p = to_tegra_plane(plane);734	struct tegra_dc_window window;735	unsigned int i;736 737	/* rien ne va plus */738	if (!new_state->crtc || !new_state->fb)739		return;740 741	if (!new_state->visible)742		return tegra_plane_atomic_disable(plane, state);743 744	memset(&window, 0, sizeof(window));745	window.src.x = new_state->src.x1 >> 16;746	window.src.y = new_state->src.y1 >> 16;747	window.src.w = drm_rect_width(&new_state->src) >> 16;748	window.src.h = drm_rect_height(&new_state->src) >> 16;749	window.dst.x = new_state->dst.x1;750	window.dst.y = new_state->dst.y1;751	window.dst.w = drm_rect_width(&new_state->dst);752	window.dst.h = drm_rect_height(&new_state->dst);753	window.bits_per_pixel = fb->format->cpp[0] * 8;754	window.reflect_x = tegra_plane_state->reflect_x;755	window.reflect_y = tegra_plane_state->reflect_y;756 757	/* copy from state */758	window.zpos = new_state->normalized_zpos;759	window.tiling = tegra_plane_state->tiling;760	window.format = tegra_plane_state->format;761	window.swap = tegra_plane_state->swap;762 763	for (i = 0; i < fb->format->num_planes; i++) {764		window.base[i] = tegra_plane_state->iova[i] + fb->offsets[i];765 766		/*767		 * Tegra uses a shared stride for UV planes. Framebuffers are768		 * already checked for this in the tegra_plane_atomic_check()769		 * function, so it's safe to ignore the V-plane pitch here.770		 */771		if (i < 2)772			window.stride[i] = fb->pitches[i];773	}774 775	tegra_dc_setup_window(p, &window);776}777 778static const struct drm_plane_helper_funcs tegra_plane_helper_funcs = {779	.prepare_fb = tegra_plane_prepare_fb,780	.cleanup_fb = tegra_plane_cleanup_fb,781	.atomic_check = tegra_plane_atomic_check,782	.atomic_disable = tegra_plane_atomic_disable,783	.atomic_update = tegra_plane_atomic_update,784};785 786static unsigned long tegra_plane_get_possible_crtcs(struct drm_device *drm)787{788	/*789	 * Ideally this would use drm_crtc_mask(), but that would require the790	 * CRTC to already be in the mode_config's list of CRTCs. However, it791	 * will only be added to that list in the drm_crtc_init_with_planes()792	 * (in tegra_dc_init()), which in turn requires registration of these793	 * planes. So we have ourselves a nice little chicken and egg problem794	 * here.795	 *796	 * We work around this by manually creating the mask from the number797	 * of CRTCs that have been registered, and should therefore always be798	 * the same as drm_crtc_index() after registration.799	 */800	return 1 << drm->mode_config.num_crtc;801}802 803static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,804						    struct tegra_dc *dc)805{806	unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm);807	enum drm_plane_type type = DRM_PLANE_TYPE_PRIMARY;808	struct tegra_plane *plane;809	unsigned int num_formats;810	const u64 *modifiers;811	const u32 *formats;812	int err;813 814	plane = kzalloc(sizeof(*plane), GFP_KERNEL);815	if (!plane)816		return ERR_PTR(-ENOMEM);817 818	/* Always use window A as primary window */819	plane->offset = 0xa00;820	plane->index = 0;821	plane->dc = dc;822 823	num_formats = dc->soc->num_primary_formats;824	formats = dc->soc->primary_formats;825	modifiers = dc->soc->modifiers;826 827	err = tegra_plane_interconnect_init(plane);828	if (err) {829		kfree(plane);830		return ERR_PTR(err);831	}832 833	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,834				       &tegra_plane_funcs, formats,835				       num_formats, modifiers, type, NULL);836	if (err < 0) {837		kfree(plane);838		return ERR_PTR(err);839	}840 841	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);842	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);843 844	err = drm_plane_create_rotation_property(&plane->base,845						 DRM_MODE_ROTATE_0,846						 DRM_MODE_ROTATE_0 |847						 DRM_MODE_ROTATE_180 |848						 DRM_MODE_REFLECT_X |849						 DRM_MODE_REFLECT_Y);850	if (err < 0)851		dev_err(dc->dev, "failed to create rotation property: %d\n",852			err);853 854	return &plane->base;855}856 857static const u32 tegra_legacy_cursor_plane_formats[] = {858	DRM_FORMAT_RGBA8888,859};860 861static const u32 tegra_cursor_plane_formats[] = {862	DRM_FORMAT_ARGB8888,863};864 865static int tegra_cursor_atomic_check(struct drm_plane *plane,866				     struct drm_atomic_state *state)867{868	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,869										 plane);870	struct tegra_plane_state *plane_state = to_tegra_plane_state(new_plane_state);871	struct tegra_plane *tegra = to_tegra_plane(plane);872	int err;873 874	plane_state->peak_memory_bandwidth = 0;875	plane_state->avg_memory_bandwidth = 0;876 877	/* no need for further checks if the plane is being disabled */878	if (!new_plane_state->crtc) {879		plane_state->total_peak_memory_bandwidth = 0;880		return 0;881	}882 883	/* scaling not supported for cursor */884	if ((new_plane_state->src_w >> 16 != new_plane_state->crtc_w) ||885	    (new_plane_state->src_h >> 16 != new_plane_state->crtc_h))886		return -EINVAL;887 888	/* only square cursors supported */889	if (new_plane_state->src_w != new_plane_state->src_h)890		return -EINVAL;891 892	if (new_plane_state->crtc_w != 32 && new_plane_state->crtc_w != 64 &&893	    new_plane_state->crtc_w != 128 && new_plane_state->crtc_w != 256)894		return -EINVAL;895 896	err = tegra_plane_state_add(tegra, new_plane_state);897	if (err < 0)898		return err;899 900	return 0;901}902 903static void __tegra_cursor_atomic_update(struct drm_plane *plane,904					 struct drm_plane_state *new_state)905{906	struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state);907	struct tegra_dc *dc = to_tegra_dc(new_state->crtc);908	struct tegra_drm *tegra = plane->dev->dev_private;909#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT910	u64 dma_mask = *dc->dev->dma_mask;911#endif912	unsigned int x, y;913	u32 value = 0;914 915	/* rien ne va plus */916	if (!new_state->crtc || !new_state->fb)917		return;918 919	/*920	 * Legacy display supports hardware clipping of the cursor, but921	 * nvdisplay relies on software to clip the cursor to the screen.922	 */923	if (!dc->soc->has_nvdisplay)924		value |= CURSOR_CLIP_DISPLAY;925 926	switch (new_state->crtc_w) {927	case 32:928		value |= CURSOR_SIZE_32x32;929		break;930 931	case 64:932		value |= CURSOR_SIZE_64x64;933		break;934 935	case 128:936		value |= CURSOR_SIZE_128x128;937		break;938 939	case 256:940		value |= CURSOR_SIZE_256x256;941		break;942 943	default:944		WARN(1, "cursor size %ux%u not supported\n",945		     new_state->crtc_w, new_state->crtc_h);946		return;947	}948 949	value |= (tegra_plane_state->iova[0] >> 10) & 0x3fffff;950	tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);951 952#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT953	value = (tegra_plane_state->iova[0] >> 32) & (dma_mask >> 32);954	tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);955#endif956 957	/* enable cursor and set blend mode */958	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);959	value |= CURSOR_ENABLE;960	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);961 962	value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);963	value &= ~CURSOR_DST_BLEND_MASK;964	value &= ~CURSOR_SRC_BLEND_MASK;965 966	if (dc->soc->has_nvdisplay)967		value &= ~CURSOR_COMPOSITION_MODE_XOR;968	else969		value |= CURSOR_MODE_NORMAL;970 971	value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC;972	value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;973	value |= CURSOR_ALPHA;974	tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);975 976	/* nvdisplay relies on software for clipping */977	if (dc->soc->has_nvdisplay) {978		struct drm_rect src;979 980		x = new_state->dst.x1;981		y = new_state->dst.y1;982 983		drm_rect_fp_to_int(&src, &new_state->src);984 985		value = (src.y1 & tegra->vmask) << 16 | (src.x1 & tegra->hmask);986		tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR);987 988		value = (drm_rect_height(&src) & tegra->vmask) << 16 |989			(drm_rect_width(&src) & tegra->hmask);990		tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR);991	} else {992		x = new_state->crtc_x;993		y = new_state->crtc_y;994	}995 996	/* position the cursor */997	value = ((y & tegra->vmask) << 16) | (x & tegra->hmask);998	tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);999}1000 1001static void tegra_cursor_atomic_update(struct drm_plane *plane,1002				       struct drm_atomic_state *state)1003{1004	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);1005 1006	__tegra_cursor_atomic_update(plane, new_state);1007}1008 1009static void tegra_cursor_atomic_disable(struct drm_plane *plane,1010					struct drm_atomic_state *state)1011{1012	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,1013									   plane);1014	struct tegra_dc *dc;1015	u32 value;1016 1017	/* rien ne va plus */1018	if (!old_state || !old_state->crtc)1019		return;1020 1021	dc = to_tegra_dc(old_state->crtc);1022 1023	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);1024	value &= ~CURSOR_ENABLE;1025	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);1026}1027 1028static int tegra_cursor_atomic_async_check(struct drm_plane *plane, struct drm_atomic_state *state)1029{1030	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);1031	struct drm_crtc_state *crtc_state;1032	int min_scale, max_scale;1033	int err;1034 1035	crtc_state = drm_atomic_get_existing_crtc_state(state, new_state->crtc);1036	if (WARN_ON(!crtc_state))1037		return -EINVAL;1038 1039	if (!crtc_state->active)1040		return -EINVAL;1041 1042	if (plane->state->crtc != new_state->crtc ||1043	    plane->state->src_w != new_state->src_w ||1044	    plane->state->src_h != new_state->src_h ||1045	    plane->state->crtc_w != new_state->crtc_w ||1046	    plane->state->crtc_h != new_state->crtc_h ||1047	    plane->state->fb != new_state->fb ||1048	    plane->state->fb == NULL)1049		return -EINVAL;1050 1051	min_scale = (1 << 16) / 8;1052	max_scale = (8 << 16) / 1;1053 1054	err = drm_atomic_helper_check_plane_state(new_state, crtc_state, min_scale, max_scale,1055						  true, true);1056	if (err < 0)1057		return err;1058 1059	if (new_state->visible != plane->state->visible)1060		return -EINVAL;1061 1062	return 0;1063}1064 1065static void tegra_cursor_atomic_async_update(struct drm_plane *plane,1066					     struct drm_atomic_state *state)1067{1068	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);1069	struct tegra_dc *dc = to_tegra_dc(new_state->crtc);1070 1071	plane->state->src_x = new_state->src_x;1072	plane->state->src_y = new_state->src_y;1073	plane->state->crtc_x = new_state->crtc_x;1074	plane->state->crtc_y = new_state->crtc_y;1075 1076	if (new_state->visible) {1077		struct tegra_plane *p = to_tegra_plane(plane);1078		u32 value;1079 1080		__tegra_cursor_atomic_update(plane, new_state);1081 1082		value = (WIN_A_ACT_REQ << p->index) << 8 | GENERAL_UPDATE;1083		tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);1084		(void)tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);1085 1086		value = (WIN_A_ACT_REQ << p->index) | GENERAL_ACT_REQ;1087		tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);1088		(void)tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);1089	}1090}1091 1092static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {1093	.prepare_fb = tegra_plane_prepare_fb,1094	.cleanup_fb = tegra_plane_cleanup_fb,1095	.atomic_check = tegra_cursor_atomic_check,1096	.atomic_update = tegra_cursor_atomic_update,1097	.atomic_disable = tegra_cursor_atomic_disable,1098	.atomic_async_check = tegra_cursor_atomic_async_check,1099	.atomic_async_update = tegra_cursor_atomic_async_update,1100};1101 1102static const uint64_t linear_modifiers[] = {1103	DRM_FORMAT_MOD_LINEAR,1104	DRM_FORMAT_MOD_INVALID1105};1106 1107static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,1108						      struct tegra_dc *dc)1109{1110	unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm);1111	struct tegra_plane *plane;1112	unsigned int num_formats;1113	const u32 *formats;1114	int err;1115 1116	plane = kzalloc(sizeof(*plane), GFP_KERNEL);1117	if (!plane)1118		return ERR_PTR(-ENOMEM);1119 1120	/*1121	 * This index is kind of fake. The cursor isn't a regular plane, but1122	 * its update and activation request bits in DC_CMD_STATE_CONTROL do1123	 * use the same programming. Setting this fake index here allows the1124	 * code in tegra_add_plane_state() to do the right thing without the1125	 * need to special-casing the cursor plane.1126	 */1127	plane->index = 6;1128	plane->dc = dc;1129 1130	if (!dc->soc->has_nvdisplay) {1131		num_formats = ARRAY_SIZE(tegra_legacy_cursor_plane_formats);1132		formats = tegra_legacy_cursor_plane_formats;1133 1134		err = tegra_plane_interconnect_init(plane);1135		if (err) {1136			kfree(plane);1137			return ERR_PTR(err);1138		}1139	} else {1140		num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);1141		formats = tegra_cursor_plane_formats;1142	}1143 1144	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,1145				       &tegra_plane_funcs, formats,1146				       num_formats, linear_modifiers,1147				       DRM_PLANE_TYPE_CURSOR, NULL);1148	if (err < 0) {1149		kfree(plane);1150		return ERR_PTR(err);1151	}1152 1153	drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs);1154	drm_plane_create_zpos_immutable_property(&plane->base, 255);1155 1156	return &plane->base;1157}1158 1159static const u32 tegra20_overlay_formats[] = {1160	DRM_FORMAT_ARGB4444,1161	DRM_FORMAT_ARGB1555,1162	DRM_FORMAT_RGB565,1163	DRM_FORMAT_RGBA5551,1164	DRM_FORMAT_ABGR8888,1165	DRM_FORMAT_ARGB8888,1166	/* non-native formats */1167	DRM_FORMAT_XRGB1555,1168	DRM_FORMAT_RGBX5551,1169	DRM_FORMAT_XBGR8888,1170	DRM_FORMAT_XRGB8888,1171	/* planar formats */1172	DRM_FORMAT_UYVY,1173	DRM_FORMAT_YUYV,1174	DRM_FORMAT_YUV420,1175	DRM_FORMAT_YUV422,1176};1177 1178static const u32 tegra114_overlay_formats[] = {1179	DRM_FORMAT_ARGB4444,1180	DRM_FORMAT_ARGB1555,1181	DRM_FORMAT_RGB565,1182	DRM_FORMAT_RGBA5551,1183	DRM_FORMAT_ABGR8888,1184	DRM_FORMAT_ARGB8888,1185	/* new on Tegra114 */1186	DRM_FORMAT_ABGR4444,1187	DRM_FORMAT_ABGR1555,1188	DRM_FORMAT_BGRA5551,1189	DRM_FORMAT_XRGB1555,1190	DRM_FORMAT_RGBX5551,1191	DRM_FORMAT_XBGR1555,1192	DRM_FORMAT_BGRX5551,1193	DRM_FORMAT_BGR565,1194	DRM_FORMAT_BGRA8888,1195	DRM_FORMAT_RGBA8888,1196	DRM_FORMAT_XRGB8888,1197	DRM_FORMAT_XBGR8888,1198	/* planar formats */1199	DRM_FORMAT_UYVY,1200	DRM_FORMAT_YUYV,1201	DRM_FORMAT_YUV420,1202	DRM_FORMAT_YUV422,1203	/* semi-planar formats */1204	DRM_FORMAT_NV12,1205	DRM_FORMAT_NV21,1206	DRM_FORMAT_NV16,1207	DRM_FORMAT_NV61,1208	DRM_FORMAT_NV24,1209	DRM_FORMAT_NV42,1210};1211 1212static const u32 tegra124_overlay_formats[] = {1213	DRM_FORMAT_ARGB4444,1214	DRM_FORMAT_ARGB1555,1215	DRM_FORMAT_RGB565,1216	DRM_FORMAT_RGBA5551,1217	DRM_FORMAT_ABGR8888,1218	DRM_FORMAT_ARGB8888,1219	/* new on Tegra114 */1220	DRM_FORMAT_ABGR4444,1221	DRM_FORMAT_ABGR1555,1222	DRM_FORMAT_BGRA5551,1223	DRM_FORMAT_XRGB1555,1224	DRM_FORMAT_RGBX5551,1225	DRM_FORMAT_XBGR1555,1226	DRM_FORMAT_BGRX5551,1227	DRM_FORMAT_BGR565,1228	DRM_FORMAT_BGRA8888,1229	DRM_FORMAT_RGBA8888,1230	DRM_FORMAT_XRGB8888,1231	DRM_FORMAT_XBGR8888,1232	/* new on Tegra124 */1233	DRM_FORMAT_RGBX8888,1234	DRM_FORMAT_BGRX8888,1235	/* planar formats */1236	DRM_FORMAT_UYVY,1237	DRM_FORMAT_YUYV,1238	DRM_FORMAT_YVYU,1239	DRM_FORMAT_VYUY,1240	DRM_FORMAT_YUV420, /* YU12 */1241	DRM_FORMAT_YUV422, /* YU16 */1242	DRM_FORMAT_YUV444, /* YU24 */1243	/* semi-planar formats */1244	DRM_FORMAT_NV12,1245	DRM_FORMAT_NV21,1246	DRM_FORMAT_NV16,1247	DRM_FORMAT_NV61,1248	DRM_FORMAT_NV24,1249	DRM_FORMAT_NV42,1250};1251 1252static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,1253						       struct tegra_dc *dc,1254						       unsigned int index,1255						       bool cursor)1256{1257	unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm);1258	struct tegra_plane *plane;1259	unsigned int num_formats;1260	enum drm_plane_type type;1261	const u32 *formats;1262	int err;1263 1264	plane = kzalloc(sizeof(*plane), GFP_KERNEL);1265	if (!plane)1266		return ERR_PTR(-ENOMEM);1267 1268	plane->offset = 0xa00 + 0x200 * index;1269	plane->index = index;1270	plane->dc = dc;1271 1272	num_formats = dc->soc->num_overlay_formats;1273	formats = dc->soc->overlay_formats;1274 1275	err = tegra_plane_interconnect_init(plane);1276	if (err) {1277		kfree(plane);1278		return ERR_PTR(err);1279	}1280 1281	if (!cursor)1282		type = DRM_PLANE_TYPE_OVERLAY;1283	else1284		type = DRM_PLANE_TYPE_CURSOR;1285 1286	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,1287				       &tegra_plane_funcs, formats,1288				       num_formats, linear_modifiers,1289				       type, NULL);1290	if (err < 0) {1291		kfree(plane);1292		return ERR_PTR(err);1293	}1294 1295	drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);1296	drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);1297 1298	err = drm_plane_create_rotation_property(&plane->base,1299						 DRM_MODE_ROTATE_0,1300						 DRM_MODE_ROTATE_0 |1301						 DRM_MODE_ROTATE_180 |1302						 DRM_MODE_REFLECT_X |1303						 DRM_MODE_REFLECT_Y);1304	if (err < 0)1305		dev_err(dc->dev, "failed to create rotation property: %d\n",1306			err);1307 1308	return &plane->base;1309}1310 1311static struct drm_plane *tegra_dc_add_shared_planes(struct drm_device *drm,1312						    struct tegra_dc *dc)1313{1314	struct drm_plane *plane, *primary = NULL;1315	unsigned int i, j;1316 1317	for (i = 0; i < dc->soc->num_wgrps; i++) {1318		const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];1319 1320		if (wgrp->dc == dc->pipe) {1321			for (j = 0; j < wgrp->num_windows; j++) {1322				unsigned int index = wgrp->windows[j];1323 1324				plane = tegra_shared_plane_create(drm, dc,1325								  wgrp->index,1326								  index);1327				if (IS_ERR(plane))1328					return plane;1329 1330				/*1331				 * Choose the first shared plane owned by this1332				 * head as the primary plane.1333				 */1334				if (!primary) {1335					plane->type = DRM_PLANE_TYPE_PRIMARY;1336					primary = plane;1337				}1338			}1339		}1340	}1341 1342	return primary;1343}1344 1345static struct drm_plane *tegra_dc_add_planes(struct drm_device *drm,1346					     struct tegra_dc *dc)1347{1348	struct drm_plane *planes[2], *primary;1349	unsigned int planes_num;1350	unsigned int i;1351	int err;1352 1353	primary = tegra_primary_plane_create(drm, dc);1354	if (IS_ERR(primary))1355		return primary;1356 1357	if (dc->soc->supports_cursor)1358		planes_num = 2;1359	else1360		planes_num = 1;1361 1362	for (i = 0; i < planes_num; i++) {1363		planes[i] = tegra_dc_overlay_plane_create(drm, dc, 1 + i,1364							  false);1365		if (IS_ERR(planes[i])) {1366			err = PTR_ERR(planes[i]);1367 1368			while (i--)1369				planes[i]->funcs->destroy(planes[i]);1370 1371			primary->funcs->destroy(primary);1372			return ERR_PTR(err);1373		}1374	}1375 1376	return primary;1377}1378 1379static void tegra_dc_destroy(struct drm_crtc *crtc)1380{1381	drm_crtc_cleanup(crtc);1382}1383 1384static void tegra_crtc_reset(struct drm_crtc *crtc)1385{1386	struct tegra_dc_state *state = kzalloc(sizeof(*state), GFP_KERNEL);1387 1388	if (crtc->state)1389		tegra_crtc_atomic_destroy_state(crtc, crtc->state);1390 1391	__drm_atomic_helper_crtc_reset(crtc, &state->base);1392}1393 1394static struct drm_crtc_state *1395tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)1396{1397	struct tegra_dc_state *state = to_dc_state(crtc->state);1398	struct tegra_dc_state *copy;1399 1400	copy = kmalloc(sizeof(*copy), GFP_KERNEL);1401	if (!copy)1402		return NULL;1403 1404	__drm_atomic_helper_crtc_duplicate_state(crtc, &copy->base);1405	copy->clk = state->clk;1406	copy->pclk = state->pclk;1407	copy->div = state->div;1408	copy->planes = state->planes;1409 1410	return &copy->base;1411}1412 1413static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,1414					    struct drm_crtc_state *state)1415{1416	__drm_atomic_helper_crtc_destroy_state(state);1417	kfree(state);1418}1419 1420#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }1421 1422static const struct debugfs_reg32 tegra_dc_regs[] = {1423	DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT),1424	DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL),1425	DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_ERROR),1426	DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT),1427	DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL),1428	DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_ERROR),1429	DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT),1430	DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL),1431	DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_ERROR),1432	DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT),1433	DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL),1434	DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_ERROR),1435	DEBUGFS_REG32(DC_CMD_CONT_SYNCPT_VSYNC),1436	DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND_OPTION0),1437	DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND),1438	DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE),1439	DEBUGFS_REG32(DC_CMD_DISPLAY_POWER_CONTROL),1440	DEBUGFS_REG32(DC_CMD_INT_STATUS),1441	DEBUGFS_REG32(DC_CMD_INT_MASK),1442	DEBUGFS_REG32(DC_CMD_INT_ENABLE),1443	DEBUGFS_REG32(DC_CMD_INT_TYPE),1444	DEBUGFS_REG32(DC_CMD_INT_POLARITY),1445	DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE1),1446	DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE2),1447	DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE3),1448	DEBUGFS_REG32(DC_CMD_STATE_ACCESS),1449	DEBUGFS_REG32(DC_CMD_STATE_CONTROL),1450	DEBUGFS_REG32(DC_CMD_DISPLAY_WINDOW_HEADER),1451	DEBUGFS_REG32(DC_CMD_REG_ACT_CONTROL),1452	DEBUGFS_REG32(DC_COM_CRC_CONTROL),1453	DEBUGFS_REG32(DC_COM_CRC_CHECKSUM),1454	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(0)),1455	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(1)),1456	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(2)),1457	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(3)),1458	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(0)),1459	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(1)),1460	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(2)),1461	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(3)),1462	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(0)),1463	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(1)),1464	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(2)),1465	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(3)),1466	DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(0)),1467	DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(1)),1468	DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(2)),1469	DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(3)),1470	DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(0)),1471	DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(1)),1472	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(0)),1473	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(1)),1474	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(2)),1475	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(3)),1476	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(4)),1477	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(5)),1478	DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(6)),1479	DEBUGFS_REG32(DC_COM_PIN_MISC_CONTROL),1480	DEBUGFS_REG32(DC_COM_PIN_PM0_CONTROL),1481	DEBUGFS_REG32(DC_COM_PIN_PM0_DUTY_CYCLE),1482	DEBUGFS_REG32(DC_COM_PIN_PM1_CONTROL),1483	DEBUGFS_REG32(DC_COM_PIN_PM1_DUTY_CYCLE),1484	DEBUGFS_REG32(DC_COM_SPI_CONTROL),1485	DEBUGFS_REG32(DC_COM_SPI_START_BYTE),1486	DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_AB),1487	DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_CD),1488	DEBUGFS_REG32(DC_COM_HSPI_CS_DC),1489	DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_A),1490	DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_B),1491	DEBUGFS_REG32(DC_COM_GPIO_CTRL),1492	DEBUGFS_REG32(DC_COM_GPIO_DEBOUNCE_COUNTER),1493	DEBUGFS_REG32(DC_COM_CRC_CHECKSUM_LATCHED),1494	DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS0),1495	DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS1),1496	DEBUGFS_REG32(DC_DISP_DISP_WIN_OPTIONS),1497	DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY),1498	DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER),1499	DEBUGFS_REG32(DC_DISP_DISP_TIMING_OPTIONS),1500	DEBUGFS_REG32(DC_DISP_REF_TO_SYNC),1501	DEBUGFS_REG32(DC_DISP_SYNC_WIDTH),1502	DEBUGFS_REG32(DC_DISP_BACK_PORCH),1503	DEBUGFS_REG32(DC_DISP_ACTIVE),1504	DEBUGFS_REG32(DC_DISP_FRONT_PORCH),1505	DEBUGFS_REG32(DC_DISP_H_PULSE0_CONTROL),1506	DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_A),1507	DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_B),1508	DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_C),1509	DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_D),1510	DEBUGFS_REG32(DC_DISP_H_PULSE1_CONTROL),1511	DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_A),1512	DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_B),1513	DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_C),1514	DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_D),1515	DEBUGFS_REG32(DC_DISP_H_PULSE2_CONTROL),1516	DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_A),1517	DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_B),1518	DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_C),1519	DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_D),1520	DEBUGFS_REG32(DC_DISP_V_PULSE0_CONTROL),1521	DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_A),1522	DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_B),1523	DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_C),1524	DEBUGFS_REG32(DC_DISP_V_PULSE1_CONTROL),1525	DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_A),1526	DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_B),1527	DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_C),1528	DEBUGFS_REG32(DC_DISP_V_PULSE2_CONTROL),1529	DEBUGFS_REG32(DC_DISP_V_PULSE2_POSITION_A),1530	DEBUGFS_REG32(DC_DISP_V_PULSE3_CONTROL),1531	DEBUGFS_REG32(DC_DISP_V_PULSE3_POSITION_A),1532	DEBUGFS_REG32(DC_DISP_M0_CONTROL),1533	DEBUGFS_REG32(DC_DISP_M1_CONTROL),1534	DEBUGFS_REG32(DC_DISP_DI_CONTROL),1535	DEBUGFS_REG32(DC_DISP_PP_CONTROL),1536	DEBUGFS_REG32(DC_DISP_PP_SELECT_A),1537	DEBUGFS_REG32(DC_DISP_PP_SELECT_B),1538	DEBUGFS_REG32(DC_DISP_PP_SELECT_C),1539	DEBUGFS_REG32(DC_DISP_PP_SELECT_D),1540	DEBUGFS_REG32(DC_DISP_DISP_CLOCK_CONTROL),1541	DEBUGFS_REG32(DC_DISP_DISP_INTERFACE_CONTROL),1542	DEBUGFS_REG32(DC_DISP_DISP_COLOR_CONTROL),1543	DEBUGFS_REG32(DC_DISP_SHIFT_CLOCK_OPTIONS),1544	DEBUGFS_REG32(DC_DISP_DATA_ENABLE_OPTIONS),1545	DEBUGFS_REG32(DC_DISP_SERIAL_INTERFACE_OPTIONS),1546	DEBUGFS_REG32(DC_DISP_LCD_SPI_OPTIONS),1547	DEBUGFS_REG32(DC_DISP_BORDER_COLOR),1548	DEBUGFS_REG32(DC_DISP_COLOR_KEY0_LOWER),1549	DEBUGFS_REG32(DC_DISP_COLOR_KEY0_UPPER),1550	DEBUGFS_REG32(DC_DISP_COLOR_KEY1_LOWER),1551	DEBUGFS_REG32(DC_DISP_COLOR_KEY1_UPPER),1552	DEBUGFS_REG32(DC_DISP_CURSOR_FOREGROUND),1553	DEBUGFS_REG32(DC_DISP_CURSOR_BACKGROUND),1554	DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR),1555	DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_NS),1556	DEBUGFS_REG32(DC_DISP_CURSOR_POSITION),1557	DEBUGFS_REG32(DC_DISP_CURSOR_POSITION_NS),1558	DEBUGFS_REG32(DC_DISP_INIT_SEQ_CONTROL),1559	DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_A),1560	DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_B),1561	DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_C),1562	DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_D),1563	DEBUGFS_REG32(DC_DISP_DC_MCCIF_FIFOCTRL),1564	DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0A_HYST),1565	DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0B_HYST),1566	DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1A_HYST),1567	DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1B_HYST),1568	DEBUGFS_REG32(DC_DISP_DAC_CRT_CTRL),1569	DEBUGFS_REG32(DC_DISP_DISP_MISC_CONTROL),1570	DEBUGFS_REG32(DC_DISP_SD_CONTROL),1571	DEBUGFS_REG32(DC_DISP_SD_CSC_COEFF),1572	DEBUGFS_REG32(DC_DISP_SD_LUT(0)),1573	DEBUGFS_REG32(DC_DISP_SD_LUT(1)),1574	DEBUGFS_REG32(DC_DISP_SD_LUT(2)),1575	DEBUGFS_REG32(DC_DISP_SD_LUT(3)),1576	DEBUGFS_REG32(DC_DISP_SD_LUT(4)),1577	DEBUGFS_REG32(DC_DISP_SD_LUT(5)),1578	DEBUGFS_REG32(DC_DISP_SD_LUT(6)),1579	DEBUGFS_REG32(DC_DISP_SD_LUT(7)),1580	DEBUGFS_REG32(DC_DISP_SD_LUT(8)),1581	DEBUGFS_REG32(DC_DISP_SD_FLICKER_CONTROL),1582	DEBUGFS_REG32(DC_DISP_DC_PIXEL_COUNT),1583	DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(0)),1584	DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(1)),1585	DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(2)),1586	DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(3)),1587	DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(4)),1588	DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(5)),1589	DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(6)),1590	DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(7)),1591	DEBUGFS_REG32(DC_DISP_SD_BL_TF(0)),1592	DEBUGFS_REG32(DC_DISP_SD_BL_TF(1)),1593	DEBUGFS_REG32(DC_DISP_SD_BL_TF(2)),1594	DEBUGFS_REG32(DC_DISP_SD_BL_TF(3)),1595	DEBUGFS_REG32(DC_DISP_SD_BL_CONTROL),1596	DEBUGFS_REG32(DC_DISP_SD_HW_K_VALUES),1597	DEBUGFS_REG32(DC_DISP_SD_MAN_K_VALUES),1598	DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_HI),1599	DEBUGFS_REG32(DC_DISP_BLEND_CURSOR_CONTROL),1600	DEBUGFS_REG32(DC_WIN_WIN_OPTIONS),1601	DEBUGFS_REG32(DC_WIN_BYTE_SWAP),1602	DEBUGFS_REG32(DC_WIN_BUFFER_CONTROL),1603	DEBUGFS_REG32(DC_WIN_COLOR_DEPTH),1604	DEBUGFS_REG32(DC_WIN_POSITION),1605	DEBUGFS_REG32(DC_WIN_SIZE),1606	DEBUGFS_REG32(DC_WIN_PRESCALED_SIZE),1607	DEBUGFS_REG32(DC_WIN_H_INITIAL_DDA),1608	DEBUGFS_REG32(DC_WIN_V_INITIAL_DDA),1609	DEBUGFS_REG32(DC_WIN_DDA_INC),1610	DEBUGFS_REG32(DC_WIN_LINE_STRIDE),1611	DEBUGFS_REG32(DC_WIN_BUF_STRIDE),1612	DEBUGFS_REG32(DC_WIN_UV_BUF_STRIDE),1613	DEBUGFS_REG32(DC_WIN_BUFFER_ADDR_MODE),1614	DEBUGFS_REG32(DC_WIN_DV_CONTROL),1615	DEBUGFS_REG32(DC_WIN_BLEND_NOKEY),1616	DEBUGFS_REG32(DC_WIN_BLEND_1WIN),1617	DEBUGFS_REG32(DC_WIN_BLEND_2WIN_X),1618	DEBUGFS_REG32(DC_WIN_BLEND_2WIN_Y),1619	DEBUGFS_REG32(DC_WIN_BLEND_3WIN_XY),1620	DEBUGFS_REG32(DC_WIN_HP_FETCH_CONTROL),1621	DEBUGFS_REG32(DC_WINBUF_START_ADDR),1622	DEBUGFS_REG32(DC_WINBUF_START_ADDR_NS),1623	DEBUGFS_REG32(DC_WINBUF_START_ADDR_U),1624	DEBUGFS_REG32(DC_WINBUF_START_ADDR_U_NS),1625	DEBUGFS_REG32(DC_WINBUF_START_ADDR_V),1626	DEBUGFS_REG32(DC_WINBUF_START_ADDR_V_NS),1627	DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET),1628	DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET_NS),1629	DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET),1630	DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET_NS),1631	DEBUGFS_REG32(DC_WINBUF_UFLOW_STATUS),1632	DEBUGFS_REG32(DC_WINBUF_AD_UFLOW_STATUS),1633	DEBUGFS_REG32(DC_WINBUF_BD_UFLOW_STATUS),1634	DEBUGFS_REG32(DC_WINBUF_CD_UFLOW_STATUS),1635};1636 1637static int tegra_dc_show_regs(struct seq_file *s, void *data)1638{1639	struct drm_info_node *node = s->private;1640	struct tegra_dc *dc = node->info_ent->data;1641	unsigned int i;1642	int err = 0;1643 1644	drm_modeset_lock(&dc->base.mutex, NULL);1645 1646	if (!dc->base.state->active) {1647		err = -EBUSY;1648		goto unlock;1649	}1650 1651	for (i = 0; i < ARRAY_SIZE(tegra_dc_regs); i++) {1652		unsigned int offset = tegra_dc_regs[i].offset;1653 1654		seq_printf(s, "%-40s %#05x %08x\n", tegra_dc_regs[i].name,1655			   offset, tegra_dc_readl(dc, offset));1656	}1657 1658unlock:1659	drm_modeset_unlock(&dc->base.mutex);1660	return err;1661}1662 1663static int tegra_dc_show_crc(struct seq_file *s, void *data)1664{1665	struct drm_info_node *node = s->private;1666	struct tegra_dc *dc = node->info_ent->data;1667	int err = 0;1668	u32 value;1669 1670	drm_modeset_lock(&dc->base.mutex, NULL);1671 1672	if (!dc->base.state->active) {1673		err = -EBUSY;1674		goto unlock;1675	}1676 1677	value = DC_COM_CRC_CONTROL_ACTIVE_DATA | DC_COM_CRC_CONTROL_ENABLE;1678	tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL);1679	tegra_dc_commit(dc);1680 1681	drm_crtc_wait_one_vblank(&dc->base);1682	drm_crtc_wait_one_vblank(&dc->base);1683 1684	value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM);1685	seq_printf(s, "%08x\n", value);1686 1687	tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);1688 1689unlock:1690	drm_modeset_unlock(&dc->base.mutex);1691	return err;1692}1693 1694static int tegra_dc_show_stats(struct seq_file *s, void *data)1695{1696	struct drm_info_node *node = s->private;1697	struct tegra_dc *dc = node->info_ent->data;1698 1699	seq_printf(s, "frames: %lu\n", dc->stats.frames);1700	seq_printf(s, "vblank: %lu\n", dc->stats.vblank);1701	seq_printf(s, "underflow: %lu\n", dc->stats.underflow);1702	seq_printf(s, "overflow: %lu\n", dc->stats.overflow);1703 1704	seq_printf(s, "frames total: %lu\n", dc->stats.frames_total);1705	seq_printf(s, "vblank total: %lu\n", dc->stats.vblank_total);1706	seq_printf(s, "underflow total: %lu\n", dc->stats.underflow_total);1707	seq_printf(s, "overflow total: %lu\n", dc->stats.overflow_total);1708 1709	return 0;1710}1711 1712static struct drm_info_list debugfs_files[] = {1713	{ "regs", tegra_dc_show_regs, 0, NULL },1714	{ "crc", tegra_dc_show_crc, 0, NULL },1715	{ "stats", tegra_dc_show_stats, 0, NULL },1716};1717 1718static int tegra_dc_late_register(struct drm_crtc *crtc)1719{1720	unsigned int i, count = ARRAY_SIZE(debugfs_files);1721	struct drm_minor *minor = crtc->dev->primary;1722	struct dentry *root;1723	struct tegra_dc *dc = to_tegra_dc(crtc);1724 1725#ifdef CONFIG_DEBUG_FS1726	root = crtc->debugfs_entry;1727#else1728	root = NULL;1729#endif1730 1731	dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),1732				    GFP_KERNEL);1733	if (!dc->debugfs_files)1734		return -ENOMEM;1735 1736	for (i = 0; i < count; i++)1737		dc->debugfs_files[i].data = dc;1738 1739	drm_debugfs_create_files(dc->debugfs_files, count, root, minor);1740 1741	return 0;1742}1743 1744static void tegra_dc_early_unregister(struct drm_crtc *crtc)1745{1746	unsigned int count = ARRAY_SIZE(debugfs_files);1747	struct drm_minor *minor = crtc->dev->primary;1748	struct tegra_dc *dc = to_tegra_dc(crtc);1749	struct dentry *root;1750 1751#ifdef CONFIG_DEBUG_FS1752	root = crtc->debugfs_entry;1753#else1754	root = NULL;1755#endif1756 1757	drm_debugfs_remove_files(dc->debugfs_files, count, root, minor);1758	kfree(dc->debugfs_files);1759	dc->debugfs_files = NULL;1760}1761 1762static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc)1763{1764	struct tegra_dc *dc = to_tegra_dc(crtc);1765 1766	/* XXX vblank syncpoints don't work with nvdisplay yet */1767	if (dc->syncpt && !dc->soc->has_nvdisplay)1768		return host1x_syncpt_read(dc->syncpt);1769 1770	/* fallback to software emulated VBLANK counter */1771	return (u32)drm_crtc_vblank_count(&dc->base);1772}1773 1774static int tegra_dc_enable_vblank(struct drm_crtc *crtc)1775{1776	struct tegra_dc *dc = to_tegra_dc(crtc);1777	u32 value;1778 1779	value = tegra_dc_readl(dc, DC_CMD_INT_MASK);1780	value |= VBLANK_INT;1781	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);1782 1783	return 0;1784}1785 1786static void tegra_dc_disable_vblank(struct drm_crtc *crtc)1787{1788	struct tegra_dc *dc = to_tegra_dc(crtc);1789	u32 value;1790 1791	value = tegra_dc_readl(dc, DC_CMD_INT_MASK);1792	value &= ~VBLANK_INT;1793	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);1794}1795 1796static const struct drm_crtc_funcs tegra_crtc_funcs = {1797	.page_flip = drm_atomic_helper_page_flip,1798	.set_config = drm_atomic_helper_set_config,1799	.destroy = tegra_dc_destroy,1800	.reset = tegra_crtc_reset,1801	.atomic_duplicate_state = tegra_crtc_atomic_duplicate_state,1802	.atomic_destroy_state = tegra_crtc_atomic_destroy_state,1803	.late_register = tegra_dc_late_register,1804	.early_unregister = tegra_dc_early_unregister,1805	.get_vblank_counter = tegra_dc_get_vblank_counter,1806	.enable_vblank = tegra_dc_enable_vblank,1807	.disable_vblank = tegra_dc_disable_vblank,1808};1809 1810static int tegra_dc_set_timings(struct tegra_dc *dc,1811				struct drm_display_mode *mode)1812{1813	unsigned int h_ref_to_sync = 1;1814	unsigned int v_ref_to_sync = 1;1815	unsigned long value;1816 1817	if (!dc->soc->has_nvdisplay) {1818		tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);1819 1820		value = (v_ref_to_sync << 16) | h_ref_to_sync;1821		tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);1822	}1823 1824	value = ((mode->vsync_end - mode->vsync_start) << 16) |1825		((mode->hsync_end - mode->hsync_start) <<  0);1826	tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);1827 1828	value = ((mode->vtotal - mode->vsync_end) << 16) |1829		((mode->htotal - mode->hsync_end) <<  0);1830	tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);1831 1832	value = ((mode->vsync_start - mode->vdisplay) << 16) |1833		((mode->hsync_start - mode->hdisplay) <<  0);1834	tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);1835 1836	value = (mode->vdisplay << 16) | mode->hdisplay;1837	tegra_dc_writel(dc, value, DC_DISP_ACTIVE);1838 1839	return 0;1840}1841 1842/**1843 * tegra_dc_state_setup_clock - check clock settings and store them in atomic1844 *     state1845 * @dc: display controller1846 * @crtc_state: CRTC atomic state1847 * @clk: parent clock for display controller1848 * @pclk: pixel clock1849 * @div: shift clock divider1850 *1851 * Returns:1852 * 0 on success or a negative error-code on failure.1853 */1854int tegra_dc_state_setup_clock(struct tegra_dc *dc,1855			       struct drm_crtc_state *crtc_state,1856			       struct clk *clk, unsigned long pclk,1857			       unsigned int div)1858{1859	struct tegra_dc_state *state = to_dc_state(crtc_state);1860 1861	if (!clk_has_parent(dc->clk, clk))1862		return -EINVAL;1863 1864	state->clk = clk;1865	state->pclk = pclk;1866	state->div = div;1867 1868	return 0;1869}1870 1871static void tegra_dc_update_voltage_state(struct tegra_dc *dc,1872					  struct tegra_dc_state *state)1873{1874	unsigned long rate, pstate;1875	struct dev_pm_opp *opp;1876	int err;1877 1878	if (!dc->has_opp_table)1879		return;1880 1881	/* calculate actual pixel clock rate which depends on internal divider */1882	rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);1883 1884	/* find suitable OPP for the rate */1885	opp = dev_pm_opp_find_freq_ceil(dc->dev, &rate);1886 1887	/*1888	 * Very high resolution modes may results in a clock rate that is1889	 * above the characterized maximum. In this case it's okay to fall1890	 * back to the characterized maximum.1891	 */1892	if (opp == ERR_PTR(-ERANGE))1893		opp = dev_pm_opp_find_freq_floor(dc->dev, &rate);1894 1895	if (IS_ERR(opp)) {1896		dev_err(dc->dev, "failed to find OPP for %luHz: %pe\n",1897			rate, opp);1898		return;1899	}1900 1901	pstate = dev_pm_opp_get_required_pstate(opp, 0);1902	dev_pm_opp_put(opp);1903 1904	/*1905	 * The minimum core voltage depends on the pixel clock rate (which1906	 * depends on internal clock divider of the CRTC) and not on the1907	 * rate of the display controller clock. This is why we're not using1908	 * dev_pm_opp_set_rate() API and instead controlling the power domain1909	 * directly.1910	 */1911	err = dev_pm_genpd_set_performance_state(dc->dev, pstate);1912	if (err)1913		dev_err(dc->dev, "failed to set power domain state to %lu: %d\n",1914			pstate, err);1915}1916 1917static void tegra_dc_set_clock_rate(struct tegra_dc *dc,1918				    struct tegra_dc_state *state)1919{1920	int err;1921 1922	err = clk_set_parent(dc->clk, state->clk);1923	if (err < 0)1924		dev_err(dc->dev, "failed to set parent clock: %d\n", err);1925 1926	/*1927	 * Outputs may not want to change the parent clock rate. This is only1928	 * relevant to Tegra20 where only a single display PLL is available.1929	 * Since that PLL would typically be used for HDMI, an internal LVDS1930	 * panel would need to be driven by some other clock such as PLL_P1931	 * which is shared with other peripherals. Changing the clock rate1932	 * should therefore be avoided.1933	 */1934	if (state->pclk > 0) {1935		err = clk_set_rate(state->clk, state->pclk);1936		if (err < 0)1937			dev_err(dc->dev,1938				"failed to set clock rate to %lu Hz\n",1939				state->pclk);1940 1941		err = clk_set_rate(dc->clk, state->pclk);1942		if (err < 0)1943			dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",1944				dc->clk, state->pclk, err);1945	}1946 1947	DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),1948		      state->div);1949	DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);1950 1951	tegra_dc_update_voltage_state(dc, state);1952}1953 1954static void tegra_dc_stop(struct tegra_dc *dc)1955{1956	u32 value;1957 1958	/* stop the display controller */1959	value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);1960	value &= ~DISP_CTRL_MODE_MASK;1961	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);1962 1963	tegra_dc_commit(dc);1964}1965 1966static bool tegra_dc_idle(struct tegra_dc *dc)1967{1968	u32 value;1969 1970	value = tegra_dc_readl_active(dc, DC_CMD_DISPLAY_COMMAND);1971 1972	return (value & DISP_CTRL_MODE_MASK) == 0;1973}1974 1975static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout)1976{1977	timeout = jiffies + msecs_to_jiffies(timeout);1978 1979	while (time_before(jiffies, timeout)) {1980		if (tegra_dc_idle(dc))1981			return 0;1982 1983		usleep_range(1000, 2000);1984	}1985 1986	dev_dbg(dc->dev, "timeout waiting for DC to become idle\n");1987	return -ETIMEDOUT;1988}1989 1990static void1991tegra_crtc_update_memory_bandwidth(struct drm_crtc *crtc,1992				   struct drm_atomic_state *state,1993				   bool prepare_bandwidth_transition)1994{1995	const struct tegra_plane_state *old_tegra_state, *new_tegra_state;1996	u32 i, new_avg_bw, old_avg_bw, new_peak_bw, old_peak_bw;1997	const struct drm_plane_state *old_plane_state;1998	const struct drm_crtc_state *old_crtc_state;1999	struct tegra_dc_window window, old_window;2000	struct tegra_dc *dc = to_tegra_dc(crtc);2001	struct tegra_plane *tegra;2002	struct drm_plane *plane;2003 2004	if (dc->soc->has_nvdisplay)2005		return;2006 2007	old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);2008 2009	if (!crtc->state->active) {2010		if (!old_crtc_state->active)2011			return;2012 2013		/*2014		 * When CRTC is disabled on DPMS, the state of attached planes2015		 * is kept unchanged. Hence we need to enforce removal of the2016		 * bandwidths from the ICC paths.2017		 */2018		drm_atomic_crtc_for_each_plane(plane, crtc) {2019			tegra = to_tegra_plane(plane);2020 2021			icc_set_bw(tegra->icc_mem, 0, 0);2022			icc_set_bw(tegra->icc_mem_vfilter, 0, 0);2023		}2024 2025		return;2026	}2027 2028	for_each_old_plane_in_state(old_crtc_state->state, plane,2029				    old_plane_state, i) {2030		old_tegra_state = to_const_tegra_plane_state(old_plane_state);2031		new_tegra_state = to_const_tegra_plane_state(plane->state);2032		tegra = to_tegra_plane(plane);2033 2034		/*2035		 * We're iterating over the global atomic state and it contains2036		 * planes from another CRTC, hence we need to filter out the2037		 * planes unrelated to this CRTC.2038		 */2039		if (tegra->dc != dc)2040			continue;2041 2042		new_avg_bw = new_tegra_state->avg_memory_bandwidth;2043		old_avg_bw = old_tegra_state->avg_memory_bandwidth;2044 2045		new_peak_bw = new_tegra_state->total_peak_memory_bandwidth;2046		old_peak_bw = old_tegra_state->total_peak_memory_bandwidth;2047 2048		/*2049		 * See the comment related to !crtc->state->active above,2050		 * which explains why bandwidths need to be updated when2051		 * CRTC is turning ON.2052		 */2053		if (new_avg_bw == old_avg_bw && new_peak_bw == old_peak_bw &&2054		    old_crtc_state->active)2055			continue;2056 2057		window.src.h = drm_rect_height(&plane->state->src) >> 16;2058		window.dst.h = drm_rect_height(&plane->state->dst);2059 2060		old_window.src.h = drm_rect_height(&old_plane_state->src) >> 16;2061		old_window.dst.h = drm_rect_height(&old_plane_state->dst);2062 2063		/*2064		 * During the preparation phase (atomic_begin), the memory2065		 * freq should go high before the DC changes are committed2066		 * if bandwidth requirement goes up, otherwise memory freq2067		 * should to stay high if BW requirement goes down.  The2068		 * opposite applies to the completion phase (post_commit).2069		 */2070		if (prepare_bandwidth_transition) {2071			new_avg_bw = max(old_avg_bw, new_avg_bw);2072			new_peak_bw = max(old_peak_bw, new_peak_bw);2073 2074			if (tegra_plane_use_vertical_filtering(tegra, &old_window))2075				window = old_window;2076		}2077 2078		icc_set_bw(tegra->icc_mem, new_avg_bw, new_peak_bw);2079 2080		if (tegra_plane_use_vertical_filtering(tegra, &window))2081			icc_set_bw(tegra->icc_mem_vfilter, new_avg_bw, new_peak_bw);2082		else2083			icc_set_bw(tegra->icc_mem_vfilter, 0, 0);2084	}2085}2086 2087static void tegra_crtc_atomic_disable(struct drm_crtc *crtc,2088				      struct drm_atomic_state *state)2089{2090	struct tegra_dc *dc = to_tegra_dc(crtc);2091	u32 value;2092	int err;2093 2094	if (!tegra_dc_idle(dc)) {2095		tegra_dc_stop(dc);2096 2097		/*2098		 * Ignore the return value, there isn't anything useful to do2099		 * in case this fails.2100		 */2101		tegra_dc_wait_idle(dc, 100);2102	}2103 2104	/*2105	 * This should really be part of the RGB encoder driver, but clearing2106	 * these bits has the side-effect of stopping the display controller.2107	 * When that happens no VBLANK interrupts will be raised. At the same2108	 * time the encoder is disabled before the display controller, so the2109	 * above code is always going to timeout waiting for the controller2110	 * to go idle.2111	 *2112	 * Given the close coupling between the RGB encoder and the display2113	 * controller doing it here is still kind of okay. None of the other2114	 * encoder drivers require these bits to be cleared.2115	 *2116	 * XXX: Perhaps given that the display controller is switched off at2117	 * this point anyway maybe clearing these bits isn't even useful for2118	 * the RGB encoder?2119	 */2120	if (dc->rgb) {2121		value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);2122		value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |2123			   PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);2124		tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);2125	}2126 2127	tegra_dc_stats_reset(&dc->stats);2128	drm_crtc_vblank_off(crtc);2129 2130	spin_lock_irq(&crtc->dev->event_lock);2131 2132	if (crtc->state->event) {2133		drm_crtc_send_vblank_event(crtc, crtc->state->event);2134		crtc->state->event = NULL;2135	}2136 2137	spin_unlock_irq(&crtc->dev->event_lock);2138 2139	err = host1x_client_suspend(&dc->client);2140	if (err < 0)2141		dev_err(dc->dev, "failed to suspend: %d\n", err);2142 2143	if (dc->has_opp_table) {2144		err = dev_pm_genpd_set_performance_state(dc->dev, 0);2145		if (err)2146			dev_err(dc->dev,2147				"failed to clear power domain state: %d\n", err);2148	}2149}2150 2151static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,2152				     struct drm_atomic_state *state)2153{2154	struct drm_display_mode *mode = &crtc->state->adjusted_mode;2155	struct tegra_dc_state *crtc_state = to_dc_state(crtc->state);2156	struct tegra_dc *dc = to_tegra_dc(crtc);2157	u32 value;2158	int err;2159 2160	/* apply PLL changes */2161	tegra_dc_set_clock_rate(dc, crtc_state);2162 2163	err = host1x_client_resume(&dc->client);2164	if (err < 0) {2165		dev_err(dc->dev, "failed to resume: %d\n", err);2166		return;2167	}2168 2169	/* initialize display controller */2170	if (dc->syncpt) {2171		u32 syncpt = host1x_syncpt_id(dc->syncpt), enable;2172 2173		if (dc->soc->has_nvdisplay)2174			enable = 1 << 31;2175		else2176			enable = 1 << 8;2177 2178		value = SYNCPT_CNTRL_NO_STALL;2179		tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);2180 2181		value = enable | syncpt;2182		tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);2183	}2184 2185	if (dc->soc->has_nvdisplay) {2186		value = DSC_TO_UF_INT | DSC_BBUF_UF_INT | DSC_RBUF_UF_INT |2187			DSC_OBUF_UF_INT;2188		tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);2189 2190		value = DSC_TO_UF_INT | DSC_BBUF_UF_INT | DSC_RBUF_UF_INT |2191			DSC_OBUF_UF_INT | SD3_BUCKET_WALK_DONE_INT |2192			HEAD_UF_INT | MSF_INT | REG_TMOUT_INT |2193			REGION_CRC_INT | V_PULSE2_INT | V_PULSE3_INT |2194			VBLANK_INT | FRAME_END_INT;2195		tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);2196 2197		value = SD3_BUCKET_WALK_DONE_INT | HEAD_UF_INT | VBLANK_INT |2198			FRAME_END_INT;2199		tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);2200 2201		value = HEAD_UF_INT | REG_TMOUT_INT | FRAME_END_INT;2202		tegra_dc_writel(dc, value, DC_CMD_INT_MASK);2203 2204		tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);2205	} else {2206		value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |2207			WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;2208		tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);2209 2210		value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |2211			WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;2212		tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);2213 2214		/* initialize timer */2215		value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |2216			WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);2217		tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);2218 2219		value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |2220			WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);2221		tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);2222 2223		value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |2224			WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;2225		tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);2226 2227		value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |2228			WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;2229		tegra_dc_writel(dc, value, DC_CMD_INT_MASK);2230	}2231 2232	if (dc->soc->supports_background_color)2233		tegra_dc_writel(dc, 0, DC_DISP_BLEND_BACKGROUND_COLOR);2234	else2235		tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);2236 2237	/* apply pixel clock changes */2238	if (!dc->soc->has_nvdisplay) {2239		value = SHIFT_CLK_DIVIDER(crtc_state->div) | PIXEL_CLK_DIVIDER_PCD1;2240		tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);2241	}2242 2243	/* program display mode */2244	tegra_dc_set_timings(dc, mode);2245 2246	/* interlacing isn't supported yet, so disable it */2247	if (dc->soc->supports_interlacing) {2248		value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);2249		value &= ~INTERLACE_ENABLE;2250		tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);2251	}2252 2253	value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);2254	value &= ~DISP_CTRL_MODE_MASK;2255	value |= DISP_CTRL_MODE_C_DISPLAY;2256	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);2257 2258	if (!dc->soc->has_nvdisplay) {2259		value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);2260		value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |2261			 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;2262		tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);2263	}2264 2265	/* enable underflow reporting and display red for missing pixels */2266	if (dc->soc->has_nvdisplay) {2267		value = UNDERFLOW_MODE_RED | UNDERFLOW_REPORT_ENABLE;2268		tegra_dc_writel(dc, value, DC_COM_RG_UNDERFLOW);2269	}2270 2271	if (dc->rgb) {2272		/* XXX: parameterize? */2273		value = SC0_H_QUALIFIER_NONE | SC1_H_QUALIFIER_NONE;2274		tegra_dc_writel(dc, value, DC_DISP_SHIFT_CLOCK_OPTIONS);2275	}2276 2277	tegra_dc_commit(dc);2278 2279	drm_crtc_vblank_on(crtc);2280}2281 2282static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,2283				    struct drm_atomic_state *state)2284{2285	unsigned long flags;2286 2287	tegra_crtc_update_memory_bandwidth(crtc, state, true);2288 2289	if (crtc->state->event) {2290		spin_lock_irqsave(&crtc->dev->event_lock, flags);2291 2292		if (drm_crtc_vblank_get(crtc) != 0)2293			drm_crtc_send_vblank_event(crtc, crtc->state->event);2294		else2295			drm_crtc_arm_vblank_event(crtc, crtc->state->event);2296 2297		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);2298 2299		crtc->state->event = NULL;2300	}2301}2302 2303static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,2304				    struct drm_atomic_state *state)2305{2306	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,2307									  crtc);2308	struct tegra_dc_state *dc_state = to_dc_state(crtc_state);2309	struct tegra_dc *dc = to_tegra_dc(crtc);2310	u32 value;2311 2312	value = dc_state->planes << 8 | GENERAL_UPDATE;2313	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);2314	value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);2315 2316	value = dc_state->planes | GENERAL_ACT_REQ;2317	tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);2318	value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);2319}2320 2321static bool tegra_plane_is_cursor(const struct drm_plane_state *state)2322{2323	const struct tegra_dc_soc_info *soc = to_tegra_dc(state->crtc)->soc;2324	const struct drm_format_info *fmt = state->fb->format;2325	unsigned int src_w = drm_rect_width(&state->src) >> 16;2326	unsigned int dst_w = drm_rect_width(&state->dst);2327 2328	if (state->plane->type != DRM_PLANE_TYPE_CURSOR)2329		return false;2330 2331	if (soc->supports_cursor)2332		return true;2333 2334	if (src_w != dst_w || fmt->num_planes != 1 || src_w * fmt->cpp[0] > 256)2335		return false;2336 2337	return true;2338}2339 2340static unsigned long2341tegra_plane_overlap_mask(struct drm_crtc_state *state,2342			 const struct drm_plane_state *plane_state)2343{2344	const struct drm_plane_state *other_state;2345	const struct tegra_plane *tegra;2346	unsigned long overlap_mask = 0;2347	struct drm_plane *plane;2348	struct drm_rect rect;2349 2350	if (!plane_state->visible || !plane_state->fb)2351		return 0;2352 2353	/*2354	 * Data-prefetch FIFO will easily help to overcome temporal memory2355	 * pressure if other plane overlaps with the cursor plane.2356	 */2357	if (tegra_plane_is_cursor(plane_state))2358		return 0;2359 2360	drm_atomic_crtc_state_for_each_plane_state(plane, other_state, state) {2361		rect = plane_state->dst;2362 2363		tegra = to_tegra_plane(other_state->plane);2364 2365		if (!other_state->visible || !other_state->fb)2366			continue;2367 2368		/*2369		 * Ignore cursor plane overlaps because it's not practical to2370		 * assume that it contributes to the bandwidth in overlapping2371		 * area if window width is small.2372		 */2373		if (tegra_plane_is_cursor(other_state))2374			continue;2375 2376		if (drm_rect_intersect(&rect, &other_state->dst))2377			overlap_mask |= BIT(tegra->index);2378	}2379 2380	return overlap_mask;2381}2382 2383static int tegra_crtc_calculate_memory_bandwidth(struct drm_crtc *crtc,2384						 struct drm_atomic_state *state)2385{2386	ulong overlap_mask[TEGRA_DC_LEGACY_PLANES_NUM] = {}, mask;2387	u32 plane_peak_bw[TEGRA_DC_LEGACY_PLANES_NUM] = {};2388	bool all_planes_overlap_simultaneously = true;2389	const struct tegra_plane_state *tegra_state;2390	const struct drm_plane_state *plane_state;2391	struct tegra_dc *dc = to_tegra_dc(crtc);2392	struct drm_crtc_state *new_state;2393	struct tegra_plane *tegra;2394	struct drm_plane *plane;2395 2396	/*2397	 * The nv-display uses shared planes.  The algorithm below assumes2398	 * maximum 3 planes per-CRTC, this assumption isn't applicable to2399	 * the nv-display.  Note that T124 support has additional windows,2400	 * but currently they aren't supported by the driver.2401	 */2402	if (dc->soc->has_nvdisplay)2403		return 0;2404 2405	new_state = drm_atomic_get_new_crtc_state(state, crtc);2406 2407	/*2408	 * For overlapping planes pixel's data is fetched for each plane at2409	 * the same time, hence bandwidths are accumulated in this case.2410	 * This needs to be taken into account for calculating total bandwidth2411	 * consumed by all planes.2412	 *2413	 * Here we get the overlapping state of each plane, which is a2414	 * bitmask of plane indices telling with what planes there is an2415	 * overlap. Note that bitmask[plane] includes BIT(plane) in order2416	 * to make further code nicer and simpler.2417	 */2418	drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, new_state) {2419		tegra_state = to_const_tegra_plane_state(plane_state);2420		tegra = to_tegra_plane(plane);2421 2422		if (WARN_ON_ONCE(tegra->index >= TEGRA_DC_LEGACY_PLANES_NUM))2423			return -EINVAL;2424 2425		plane_peak_bw[tegra->index] = tegra_state->peak_memory_bandwidth;2426		mask = tegra_plane_overlap_mask(new_state, plane_state);2427		overlap_mask[tegra->index] = mask;2428 2429		if (hweight_long(mask) != 3)2430			all_planes_overlap_simultaneously = false;2431	}2432 2433	/*2434	 * Then we calculate maximum bandwidth of each plane state.2435	 * The bandwidth includes the plane BW + BW of the "simultaneously"2436	 * overlapping planes, where "simultaneously" means areas where DC2437	 * fetches from the planes simultaneously during of scan-out process.2438	 *2439	 * For example, if plane A overlaps with planes B and C, but B and C2440	 * don't overlap, then the peak bandwidth will be either in area where2441	 * A-and-B or A-and-C planes overlap.2442	 *2443	 * The plane_peak_bw[] contains peak memory bandwidth values of2444	 * each plane, this information is needed by interconnect provider2445	 * in order to set up latency allowance based on the peak BW, see2446	 * tegra_crtc_update_memory_bandwidth().2447	 */2448	drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, new_state) {2449		u32 i, old_peak_bw, new_peak_bw, overlap_bw = 0;2450 2451		/*2452		 * Note that plane's atomic check doesn't touch the2453		 * total_peak_memory_bandwidth of enabled plane, hence the2454		 * current state contains the old bandwidth state from the2455		 * previous CRTC commit.2456		 */2457		tegra_state = to_const_tegra_plane_state(plane_state);2458		tegra = to_tegra_plane(plane);2459 2460		for_each_set_bit(i, &overlap_mask[tegra->index], 3) {2461			if (i == tegra->index)2462				continue;2463 2464			if (all_planes_overlap_simultaneously)2465				overlap_bw += plane_peak_bw[i];2466			else2467				overlap_bw = max(overlap_bw, plane_peak_bw[i]);2468		}2469 2470		new_peak_bw = plane_peak_bw[tegra->index] + overlap_bw;2471		old_peak_bw = tegra_state->total_peak_memory_bandwidth;2472 2473		/*2474		 * If plane's peak bandwidth changed (for example plane isn't2475		 * overlapped anymore) and plane isn't in the atomic state,2476		 * then add plane to the state in order to have the bandwidth2477		 * updated.2478		 */2479		if (old_peak_bw != new_peak_bw) {2480			struct tegra_plane_state *new_tegra_state;2481			struct drm_plane_state *new_plane_state;2482 2483			new_plane_state = drm_atomic_get_plane_state(state, plane);2484			if (IS_ERR(new_plane_state))2485				return PTR_ERR(new_plane_state);2486 2487			new_tegra_state = to_tegra_plane_state(new_plane_state);2488			new_tegra_state->total_peak_memory_bandwidth = new_peak_bw;2489		}2490	}2491 2492	return 0;2493}2494 2495static int tegra_crtc_atomic_check(struct drm_crtc *crtc,2496				   struct drm_atomic_state *state)2497{2498	int err;2499 2500	err = tegra_crtc_calculate_memory_bandwidth(crtc, state);2501	if (err)2502		return err;2503 2504	return 0;2505}2506 2507void tegra_crtc_atomic_post_commit(struct drm_crtc *crtc,2508				   struct drm_atomic_state *state)2509{2510	/*2511	 * Display bandwidth is allowed to go down only once hardware state2512	 * is known to be armed, i.e. state was committed and VBLANK event2513	 * received.2514	 */2515	tegra_crtc_update_memory_bandwidth(crtc, state, false);2516}2517 2518static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {2519	.atomic_check = tegra_crtc_atomic_check,2520	.atomic_begin = tegra_crtc_atomic_begin,2521	.atomic_flush = tegra_crtc_atomic_flush,2522	.atomic_enable = tegra_crtc_atomic_enable,2523	.atomic_disable = tegra_crtc_atomic_disable,2524};2525 2526static irqreturn_t tegra_dc_irq(int irq, void *data)2527{2528	struct tegra_dc *dc = data;2529	unsigned long status;2530 2531	status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);2532	tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);2533 2534	if (status & FRAME_END_INT) {2535		/*2536		dev_dbg(dc->dev, "%s(): frame end\n", __func__);2537		*/2538		dc->stats.frames_total++;2539		dc->stats.frames++;2540	}2541 2542	if (status & VBLANK_INT) {2543		/*2544		dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);2545		*/2546		drm_crtc_handle_vblank(&dc->base);2547		dc->stats.vblank_total++;2548		dc->stats.vblank++;2549	}2550 2551	if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {2552		/*2553		dev_dbg(dc->dev, "%s(): underflow\n", __func__);2554		*/2555		dc->stats.underflow_total++;2556		dc->stats.underflow++;2557	}2558 2559	if (status & (WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT)) {2560		/*2561		dev_dbg(dc->dev, "%s(): overflow\n", __func__);2562		*/2563		dc->stats.overflow_total++;2564		dc->stats.overflow++;2565	}2566 2567	if (status & HEAD_UF_INT) {2568		dev_dbg_ratelimited(dc->dev, "%s(): head underflow\n", __func__);2569		dc->stats.underflow_total++;2570		dc->stats.underflow++;2571	}2572 2573	return IRQ_HANDLED;2574}2575 2576static bool tegra_dc_has_window_groups(struct tegra_dc *dc)2577{2578	unsigned int i;2579 2580	if (!dc->soc->wgrps)2581		return true;2582 2583	for (i = 0; i < dc->soc->num_wgrps; i++) {2584		const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];2585 2586		if (wgrp->dc == dc->pipe && wgrp->num_windows > 0)2587			return true;2588	}2589 2590	return false;2591}2592 2593static int tegra_dc_early_init(struct host1x_client *client)2594{2595	struct drm_device *drm = dev_get_drvdata(client->host);2596	struct tegra_drm *tegra = drm->dev_private;2597 2598	tegra->num_crtcs++;2599 2600	return 0;2601}2602 2603static int tegra_dc_init(struct host1x_client *client)2604{2605	struct drm_device *drm = dev_get_drvdata(client->host);2606	unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;2607	struct tegra_dc *dc = host1x_client_to_dc(client);2608	struct tegra_drm *tegra = drm->dev_private;2609	struct drm_plane *primary = NULL;2610	struct drm_plane *cursor = NULL;2611	int err;2612 2613	/*2614	 * DC has been reset by now, so VBLANK syncpoint can be released2615	 * for general use.2616	 */2617	host1x_syncpt_release_vblank_reservation(client, 26 + dc->pipe);2618 2619	/*2620	 * XXX do not register DCs with no window groups because we cannot2621	 * assign a primary plane to them, which in turn will cause KMS to2622	 * crash.2623	 */2624	if (!tegra_dc_has_window_groups(dc))2625		return 0;2626 2627	/*2628	 * Set the display hub as the host1x client parent for the display2629	 * controller. This is needed for the runtime reference counting that2630	 * ensures the display hub is always powered when any of the display2631	 * controllers are.2632	 */2633	if (dc->soc->has_nvdisplay)2634		client->parent = &tegra->hub->client;2635 2636	dc->syncpt = host1x_syncpt_request(client, flags);2637	if (!dc->syncpt)2638		dev_warn(dc->dev, "failed to allocate syncpoint\n");2639 2640	err = host1x_client_iommu_attach(client);2641	if (err < 0 && err != -ENODEV) {2642		dev_err(client->dev, "failed to attach to domain: %d\n", err);2643		return err;2644	}2645 2646	if (dc->soc->wgrps)2647		primary = tegra_dc_add_shared_planes(drm, dc);2648	else2649		primary = tegra_dc_add_planes(drm, dc);2650 2651	if (IS_ERR(primary)) {2652		err = PTR_ERR(primary);2653		goto cleanup;2654	}2655 2656	if (dc->soc->supports_cursor) {2657		cursor = tegra_dc_cursor_plane_create(drm, dc);2658		if (IS_ERR(cursor)) {2659			err = PTR_ERR(cursor);2660			goto cleanup;2661		}2662	} else {2663		/* dedicate one overlay to mouse cursor */2664		cursor = tegra_dc_overlay_plane_create(drm, dc, 2, true);2665		if (IS_ERR(cursor)) {2666			err = PTR_ERR(cursor);2667			goto cleanup;2668		}2669	}2670 2671	err = drm_crtc_init_with_planes(drm, &dc->base, primary, cursor,2672					&tegra_crtc_funcs, NULL);2673	if (err < 0)2674		goto cleanup;2675 2676	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);2677 2678	/*2679	 * Keep track of the minimum pitch alignment across all display2680	 * controllers.2681	 */2682	if (dc->soc->pitch_align > tegra->pitch_align)2683		tegra->pitch_align = dc->soc->pitch_align;2684 2685	/* track maximum resolution */2686	if (dc->soc->has_nvdisplay)2687		drm->mode_config.max_width = drm->mode_config.max_height = 16384;2688	else2689		drm->mode_config.max_width = drm->mode_config.max_height = 4096;2690 2691	err = tegra_dc_rgb_init(drm, dc);2692	if (err < 0 && err != -ENODEV) {2693		dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);2694		goto cleanup;2695	}2696 2697	err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,2698			       dev_name(dc->dev), dc);2699	if (err < 0) {2700		dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,2701			err);2702		goto cleanup;2703	}2704 2705	/*2706	 * Inherit the DMA parameters (such as maximum segment size) from the2707	 * parent host1x device.2708	 */2709	client->dev->dma_parms = client->host->dma_parms;2710 2711	return 0;2712 2713cleanup:2714	if (!IS_ERR_OR_NULL(cursor))2715		drm_plane_cleanup(cursor);2716 2717	if (!IS_ERR(primary))2718		drm_plane_cleanup(primary);2719 2720	host1x_client_iommu_detach(client);2721	host1x_syncpt_put(dc->syncpt);2722 2723	return err;2724}2725 2726static int tegra_dc_exit(struct host1x_client *client)2727{2728	struct tegra_dc *dc = host1x_client_to_dc(client);2729	int err;2730 2731	if (!tegra_dc_has_window_groups(dc))2732		return 0;2733 2734	/* avoid a dangling pointer just in case this disappears */2735	client->dev->dma_parms = NULL;2736 2737	devm_free_irq(dc->dev, dc->irq, dc);2738 2739	err = tegra_dc_rgb_exit(dc);2740	if (err) {2741		dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);2742		return err;2743	}2744 2745	host1x_client_iommu_detach(client);2746	host1x_syncpt_put(dc->syncpt);2747 2748	return 0;2749}2750 2751static int tegra_dc_late_exit(struct host1x_client *client)2752{2753	struct drm_device *drm = dev_get_drvdata(client->host);2754	struct tegra_drm *tegra = drm->dev_private;2755 2756	tegra->num_crtcs--;2757 2758	return 0;2759}2760 2761static int tegra_dc_runtime_suspend(struct host1x_client *client)2762{2763	struct tegra_dc *dc = host1x_client_to_dc(client);2764	struct device *dev = client->dev;2765	int err;2766 2767	err = reset_control_assert(dc->rst);2768	if (err < 0) {2769		dev_err(dev, "failed to assert reset: %d\n", err);2770		return err;2771	}2772 2773	if (dc->soc->has_powergate)2774		tegra_powergate_power_off(dc->powergate);2775 2776	clk_disable_unprepare(dc->clk);2777	pm_runtime_put_sync(dev);2778 2779	return 0;2780}2781 2782static int tegra_dc_runtime_resume(struct host1x_client *client)2783{2784	struct tegra_dc *dc = host1x_client_to_dc(client);2785	struct device *dev = client->dev;2786	int err;2787 2788	err = pm_runtime_resume_and_get(dev);2789	if (err < 0) {2790		dev_err(dev, "failed to get runtime PM: %d\n", err);2791		return err;2792	}2793 2794	if (dc->soc->has_powergate) {2795		err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,2796							dc->rst);2797		if (err < 0) {2798			dev_err(dev, "failed to power partition: %d\n", err);2799			goto put_rpm;2800		}2801	} else {2802		err = clk_prepare_enable(dc->clk);2803		if (err < 0) {2804			dev_err(dev, "failed to enable clock: %d\n", err);2805			goto put_rpm;2806		}2807 2808		err = reset_control_deassert(dc->rst);2809		if (err < 0) {2810			dev_err(dev, "failed to deassert reset: %d\n", err);2811			goto disable_clk;2812		}2813	}2814 2815	return 0;2816 2817disable_clk:2818	clk_disable_unprepare(dc->clk);2819put_rpm:2820	pm_runtime_put_sync(dev);2821	return err;2822}2823 2824static const struct host1x_client_ops dc_client_ops = {2825	.early_init = tegra_dc_early_init,2826	.init = tegra_dc_init,2827	.exit = tegra_dc_exit,2828	.late_exit = tegra_dc_late_exit,2829	.suspend = tegra_dc_runtime_suspend,2830	.resume = tegra_dc_runtime_resume,2831};2832 2833static const struct tegra_dc_soc_info tegra20_dc_soc_info = {2834	.supports_background_color = false,2835	.supports_interlacing = false,2836	.supports_cursor = false,2837	.supports_block_linear = false,2838	.supports_sector_layout = false,2839	.has_legacy_blending = true,2840	.pitch_align = 8,2841	.has_powergate = false,2842	.coupled_pm = true,2843	.has_nvdisplay = false,2844	.num_primary_formats = ARRAY_SIZE(tegra20_primary_formats),2845	.primary_formats = tegra20_primary_formats,2846	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),2847	.overlay_formats = tegra20_overlay_formats,2848	.modifiers = tegra20_modifiers,2849	.has_win_a_without_filters = true,2850	.has_win_b_vfilter_mem_client = true,2851	.has_win_c_without_vert_filter = true,2852	.plane_tiled_memory_bandwidth_x2 = false,2853	.has_pll_d2_out0 = false,2854};2855 2856static const struct tegra_dc_soc_info tegra30_dc_soc_info = {2857	.supports_background_color = false,2858	.supports_interlacing = false,2859	.supports_cursor = false,2860	.supports_block_linear = false,2861	.supports_sector_layout = false,2862	.has_legacy_blending = true,2863	.pitch_align = 8,2864	.has_powergate = false,2865	.coupled_pm = false,2866	.has_nvdisplay = false,2867	.num_primary_formats = ARRAY_SIZE(tegra20_primary_formats),2868	.primary_formats = tegra20_primary_formats,2869	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),2870	.overlay_formats = tegra20_overlay_formats,2871	.modifiers = tegra20_modifiers,2872	.has_win_a_without_filters = false,2873	.has_win_b_vfilter_mem_client = true,2874	.has_win_c_without_vert_filter = false,2875	.plane_tiled_memory_bandwidth_x2 = true,2876	.has_pll_d2_out0 = true,2877};2878 2879static const struct tegra_dc_soc_info tegra114_dc_soc_info = {2880	.supports_background_color = false,2881	.supports_interlacing = false,2882	.supports_cursor = false,2883	.supports_block_linear = false,2884	.supports_sector_layout = false,2885	.has_legacy_blending = true,2886	.pitch_align = 64,2887	.has_powergate = true,2888	.coupled_pm = false,2889	.has_nvdisplay = false,2890	.num_primary_formats = ARRAY_SIZE(tegra114_primary_formats),2891	.primary_formats = tegra114_primary_formats,2892	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),2893	.overlay_formats = tegra114_overlay_formats,2894	.modifiers = tegra20_modifiers,2895	.has_win_a_without_filters = false,2896	.has_win_b_vfilter_mem_client = false,2897	.has_win_c_without_vert_filter = false,2898	.plane_tiled_memory_bandwidth_x2 = true,2899	.has_pll_d2_out0 = true,2900};2901 2902static const struct tegra_dc_soc_info tegra124_dc_soc_info = {2903	.supports_background_color = true,2904	.supports_interlacing = true,2905	.supports_cursor = true,2906	.supports_block_linear = true,2907	.supports_sector_layout = false,2908	.has_legacy_blending = false,2909	.pitch_align = 64,2910	.has_powergate = true,2911	.coupled_pm = false,2912	.has_nvdisplay = false,2913	.num_primary_formats = ARRAY_SIZE(tegra124_primary_formats),2914	.primary_formats = tegra124_primary_formats,2915	.num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats),2916	.overlay_formats = tegra124_overlay_formats,2917	.modifiers = tegra124_modifiers,2918	.has_win_a_without_filters = false,2919	.has_win_b_vfilter_mem_client = false,2920	.has_win_c_without_vert_filter = false,2921	.plane_tiled_memory_bandwidth_x2 = false,2922	.has_pll_d2_out0 = true,2923};2924 2925static const struct tegra_dc_soc_info tegra210_dc_soc_info = {2926	.supports_background_color = true,2927	.supports_interlacing = true,2928	.supports_cursor = true,2929	.supports_block_linear = true,2930	.supports_sector_layout = false,2931	.has_legacy_blending = false,2932	.pitch_align = 64,2933	.has_powergate = true,2934	.coupled_pm = false,2935	.has_nvdisplay = false,2936	.num_primary_formats = ARRAY_SIZE(tegra114_primary_formats),2937	.primary_formats = tegra114_primary_formats,2938	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),2939	.overlay_formats = tegra114_overlay_formats,2940	.modifiers = tegra124_modifiers,2941	.has_win_a_without_filters = false,2942	.has_win_b_vfilter_mem_client = false,2943	.has_win_c_without_vert_filter = false,2944	.plane_tiled_memory_bandwidth_x2 = false,2945	.has_pll_d2_out0 = true,2946};2947 2948static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {2949	{2950		.index = 0,2951		.dc = 0,2952		.windows = (const unsigned int[]) { 0 },2953		.num_windows = 1,2954	}, {2955		.index = 1,2956		.dc = 1,2957		.windows = (const unsigned int[]) { 1 },2958		.num_windows = 1,2959	}, {2960		.index = 2,2961		.dc = 1,2962		.windows = (const unsigned int[]) { 2 },2963		.num_windows = 1,2964	}, {2965		.index = 3,2966		.dc = 2,2967		.windows = (const unsigned int[]) { 3 },2968		.num_windows = 1,2969	}, {2970		.index = 4,2971		.dc = 2,2972		.windows = (const unsigned int[]) { 4 },2973		.num_windows = 1,2974	}, {2975		.index = 5,2976		.dc = 2,2977		.windows = (const unsigned int[]) { 5 },2978		.num_windows = 1,2979	},2980};2981 2982static const struct tegra_dc_soc_info tegra186_dc_soc_info = {2983	.supports_background_color = true,2984	.supports_interlacing = true,2985	.supports_cursor = true,2986	.supports_block_linear = true,2987	.supports_sector_layout = false,2988	.has_legacy_blending = false,2989	.pitch_align = 64,2990	.has_powergate = false,2991	.coupled_pm = false,2992	.has_nvdisplay = true,2993	.wgrps = tegra186_dc_wgrps,2994	.num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps),2995	.plane_tiled_memory_bandwidth_x2 = false,2996	.has_pll_d2_out0 = false,2997};2998 2999static const struct tegra_windowgroup_soc tegra194_dc_wgrps[] = {3000	{3001		.index = 0,3002		.dc = 0,3003		.windows = (const unsigned int[]) { 0 },3004		.num_windows = 1,3005	}, {3006		.index = 1,3007		.dc = 1,3008		.windows = (const unsigned int[]) { 1 },3009		.num_windows = 1,3010	}, {3011		.index = 2,3012		.dc = 1,3013		.windows = (const unsigned int[]) { 2 },3014		.num_windows = 1,3015	}, {3016		.index = 3,3017		.dc = 2,3018		.windows = (const unsigned int[]) { 3 },3019		.num_windows = 1,3020	}, {3021		.index = 4,3022		.dc = 2,3023		.windows = (const unsigned int[]) { 4 },3024		.num_windows = 1,3025	}, {3026		.index = 5,3027		.dc = 2,3028		.windows = (const unsigned int[]) { 5 },3029		.num_windows = 1,3030	},3031};3032 3033static const struct tegra_dc_soc_info tegra194_dc_soc_info = {3034	.supports_background_color = true,3035	.supports_interlacing = true,3036	.supports_cursor = true,3037	.supports_block_linear = true,3038	.supports_sector_layout = true,3039	.has_legacy_blending = false,3040	.pitch_align = 64,3041	.has_powergate = false,3042	.coupled_pm = false,3043	.has_nvdisplay = true,3044	.wgrps = tegra194_dc_wgrps,3045	.num_wgrps = ARRAY_SIZE(tegra194_dc_wgrps),3046	.plane_tiled_memory_bandwidth_x2 = false,3047	.has_pll_d2_out0 = false,3048};3049 3050static const struct of_device_id tegra_dc_of_match[] = {3051	{3052		.compatible = "nvidia,tegra194-dc",3053		.data = &tegra194_dc_soc_info,3054	}, {3055		.compatible = "nvidia,tegra186-dc",3056		.data = &tegra186_dc_soc_info,3057	}, {3058		.compatible = "nvidia,tegra210-dc",3059		.data = &tegra210_dc_soc_info,3060	}, {3061		.compatible = "nvidia,tegra124-dc",3062		.data = &tegra124_dc_soc_info,3063	}, {3064		.compatible = "nvidia,tegra114-dc",3065		.data = &tegra114_dc_soc_info,3066	}, {3067		.compatible = "nvidia,tegra30-dc",3068		.data = &tegra30_dc_soc_info,3069	}, {3070		.compatible = "nvidia,tegra20-dc",3071		.data = &tegra20_dc_soc_info,3072	}, {3073		/* sentinel */3074	}3075};3076MODULE_DEVICE_TABLE(of, tegra_dc_of_match);3077 3078static int tegra_dc_parse_dt(struct tegra_dc *dc)3079{3080	struct device_node *np;3081	u32 value = 0;3082	int err;3083 3084	err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);3085	if (err < 0) {3086		dev_err(dc->dev, "missing \"nvidia,head\" property\n");3087 3088		/*3089		 * If the nvidia,head property isn't present, try to find the3090		 * correct head number by looking up the position of this3091		 * display controller's node within the device tree. Assuming3092		 * that the nodes are ordered properly in the DTS file and3093		 * that the translation into a flattened device tree blob3094		 * preserves that ordering this will actually yield the right3095		 * head number.3096		 *3097		 * If those assumptions don't hold, this will still work for3098		 * cases where only a single display controller is used.3099		 */3100		for_each_matching_node(np, tegra_dc_of_match) {3101			if (np == dc->dev->of_node) {3102				of_node_put(np);3103				break;3104			}3105 3106			value++;3107		}3108	}3109 3110	dc->pipe = value;3111 3112	return 0;3113}3114 3115static int tegra_dc_match_by_pipe(struct device *dev, const void *data)3116{3117	struct tegra_dc *dc = dev_get_drvdata(dev);3118	unsigned int pipe = (unsigned long)(void *)data;3119 3120	return dc->pipe == pipe;3121}3122 3123static int tegra_dc_couple(struct tegra_dc *dc)3124{3125	/*3126	 * On Tegra20, DC1 requires DC0 to be taken out of reset in order to3127	 * be enabled, otherwise CPU hangs on writing to CMD_DISPLAY_COMMAND /3128	 * POWER_CONTROL registers during CRTC enabling.3129	 */3130	if (dc->soc->coupled_pm && dc->pipe == 1) {3131		struct device *companion;3132		struct tegra_dc *parent;3133 3134		companion = driver_find_device(dc->dev->driver, NULL, (const void *)0,3135					       tegra_dc_match_by_pipe);3136		if (!companion)3137			return -EPROBE_DEFER;3138 3139		parent = dev_get_drvdata(companion);3140		dc->client.parent = &parent->client;3141 3142		dev_dbg(dc->dev, "coupled to %s\n", dev_name(companion));3143	}3144 3145	return 0;3146}3147 3148static int tegra_dc_init_opp_table(struct tegra_dc *dc)3149{3150	struct tegra_core_opp_params opp_params = {};3151	int err;3152 3153	err = devm_tegra_core_dev_init_opp_table(dc->dev, &opp_params);3154	if (err && err != -ENODEV)3155		return err;3156 3157	if (err)3158		dc->has_opp_table = false;3159	else3160		dc->has_opp_table = true;3161 3162	return 0;3163}3164 3165static int tegra_dc_probe(struct platform_device *pdev)3166{3167	u64 dma_mask = dma_get_mask(pdev->dev.parent);3168	struct tegra_dc *dc;3169	int err;3170 3171	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);3172	if (err < 0) {3173		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);3174		return err;3175	}3176 3177	dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);3178	if (!dc)3179		return -ENOMEM;3180 3181	dc->soc = of_device_get_match_data(&pdev->dev);3182 3183	INIT_LIST_HEAD(&dc->list);3184	dc->dev = &pdev->dev;3185 3186	err = tegra_dc_parse_dt(dc);3187	if (err < 0)3188		return err;3189 3190	err = tegra_dc_couple(dc);3191	if (err < 0)3192		return err;3193 3194	dc->clk = devm_clk_get(&pdev->dev, NULL);3195	if (IS_ERR(dc->clk)) {3196		dev_err(&pdev->dev, "failed to get clock\n");3197		return PTR_ERR(dc->clk);3198	}3199 3200	dc->rst = devm_reset_control_get(&pdev->dev, "dc");3201	if (IS_ERR(dc->rst)) {3202		dev_err(&pdev->dev, "failed to get reset\n");3203		return PTR_ERR(dc->rst);3204	}3205 3206	/* assert reset and disable clock */3207	err = clk_prepare_enable(dc->clk);3208	if (err < 0)3209		return err;3210 3211	usleep_range(2000, 4000);3212 3213	err = reset_control_assert(dc->rst);3214	if (err < 0) {3215		clk_disable_unprepare(dc->clk);3216		return err;3217	}3218 3219	usleep_range(2000, 4000);3220 3221	clk_disable_unprepare(dc->clk);3222 3223	if (dc->soc->has_powergate) {3224		if (dc->pipe == 0)3225			dc->powergate = TEGRA_POWERGATE_DIS;3226		else3227			dc->powergate = TEGRA_POWERGATE_DISB;3228 3229		tegra_powergate_power_off(dc->powergate);3230	}3231 3232	err = tegra_dc_init_opp_table(dc);3233	if (err < 0)3234		return err;3235 3236	dc->regs = devm_platform_ioremap_resource(pdev, 0);3237	if (IS_ERR(dc->regs))3238		return PTR_ERR(dc->regs);3239 3240	dc->irq = platform_get_irq(pdev, 0);3241	if (dc->irq < 0)3242		return -ENXIO;3243 3244	err = tegra_dc_rgb_probe(dc);3245	if (err < 0 && err != -ENODEV)3246		return dev_err_probe(&pdev->dev, err,3247				     "failed to probe RGB output\n");3248 3249	platform_set_drvdata(pdev, dc);3250	pm_runtime_enable(&pdev->dev);3251 3252	INIT_LIST_HEAD(&dc->client.list);3253	dc->client.ops = &dc_client_ops;3254	dc->client.dev = &pdev->dev;3255 3256	err = host1x_client_register(&dc->client);3257	if (err < 0) {3258		dev_err(&pdev->dev, "failed to register host1x client: %d\n",3259			err);3260		goto disable_pm;3261	}3262 3263	return 0;3264 3265disable_pm:3266	pm_runtime_disable(&pdev->dev);3267	tegra_dc_rgb_remove(dc);3268 3269	return err;3270}3271 3272static void tegra_dc_remove(struct platform_device *pdev)3273{3274	struct tegra_dc *dc = platform_get_drvdata(pdev);3275 3276	host1x_client_unregister(&dc->client);3277 3278	tegra_dc_rgb_remove(dc);3279 3280	pm_runtime_disable(&pdev->dev);3281}3282 3283struct platform_driver tegra_dc_driver = {3284	.driver = {3285		.name = "tegra-dc",3286		.of_match_table = tegra_dc_of_match,3287	},3288	.probe = tegra_dc_probe,3289	.remove_new = tegra_dc_remove,3290};3291