diff options
Diffstat (limited to 'drivers/gpu/drm/tegra/hub.c')
| -rw-r--r-- | drivers/gpu/drm/tegra/hub.c | 103 | 
1 files changed, 73 insertions, 30 deletions
| diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index 5ce771cba133..bfae8a02f55b 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -55,6 +55,18 @@ static const u64 tegra_shared_plane_modifiers[] = {  	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),  	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),  	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5), +	/* +	 * The GPU sector layout is only supported on Tegra194, but these will +	 * be filtered out later on by ->format_mod_supported() on SoCs where +	 * it isn't supported. +	 */ +	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, +	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, +	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, +	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, +	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, +	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5) | DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT, +	/* sentinel */  	DRM_FORMAT_MOD_INVALID  }; @@ -336,25 +348,27 @@ static void tegra_dc_remove_shared_plane(struct tegra_dc *dc,  }  static int tegra_shared_plane_atomic_check(struct drm_plane *plane, -					   struct drm_plane_state *state) +					   struct drm_atomic_state *state)  { -	struct tegra_plane_state *plane_state = to_tegra_plane_state(state); +	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, +										 plane); +	struct tegra_plane_state *plane_state = to_tegra_plane_state(new_plane_state);  	struct tegra_shared_plane *tegra = to_tegra_shared_plane(plane);  	struct tegra_bo_tiling *tiling = &plane_state->tiling; -	struct tegra_dc *dc = to_tegra_dc(state->crtc); +	struct tegra_dc *dc = to_tegra_dc(new_plane_state->crtc);  	int err;  	/* no need for further checks if the plane is being disabled */ -	if (!state->crtc || !state->fb) +	if (!new_plane_state->crtc || !new_plane_state->fb)  		return 0; -	err = tegra_plane_format(state->fb->format->format, +	err = tegra_plane_format(new_plane_state->fb->format->format,  				 &plane_state->format,  				 &plane_state->swap);  	if (err < 0)  		return err; -	err = tegra_fb_get_tiling(state->fb, tiling); +	err = tegra_fb_get_tiling(new_plane_state->fb, tiling);  	if (err < 0)  		return err; @@ -364,13 +378,19 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane,  		return -EINVAL;  	} +	if (tiling->sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU && +	    !dc->soc->supports_sector_layout) { +		DRM_ERROR("hardware doesn't support GPU sector layout\n"); +		return -EINVAL; +	} +  	/*  	 * Tegra doesn't support different strides for U and V planes so we  	 * error out if the user tries to display a framebuffer with such a  	 * configuration.  	 */ -	if (state->fb->format->num_planes > 2) { -		if (state->fb->pitches[2] != state->fb->pitches[1]) { +	if (new_plane_state->fb->format->num_planes > 2) { +		if (new_plane_state->fb->pitches[2] != new_plane_state->fb->pitches[1]) {  			DRM_ERROR("unsupported UV-plane configuration\n");  			return -EINVAL;  		} @@ -378,7 +398,7 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane,  	/* XXX scaling is not yet supported, add a check here */ -	err = tegra_plane_state_add(&tegra->base, state); +	err = tegra_plane_state_add(&tegra->base, new_plane_state);  	if (err < 0)  		return err; @@ -386,8 +406,10 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane,  }  static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, -					      struct drm_plane_state *old_state) +					      struct drm_atomic_state *state)  { +	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, +									   plane);  	struct tegra_plane *p = to_tegra_plane(plane);  	struct tegra_dc *dc;  	u32 value; @@ -423,23 +445,25 @@ static void tegra_shared_plane_atomic_disable(struct drm_plane *plane,  }  static void tegra_shared_plane_atomic_update(struct drm_plane *plane, -					     struct drm_plane_state *old_state) +					     struct drm_atomic_state *state)  { -	struct tegra_plane_state *state = to_tegra_plane_state(plane->state); -	struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); -	unsigned int zpos = plane->state->normalized_zpos; -	struct drm_framebuffer *fb = plane->state->fb; +	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, +									   plane); +	struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state); +	struct tegra_dc *dc = to_tegra_dc(new_state->crtc); +	unsigned int zpos = new_state->normalized_zpos; +	struct drm_framebuffer *fb = new_state->fb;  	struct tegra_plane *p = to_tegra_plane(plane);  	dma_addr_t base;  	u32 value;  	int err;  	/* rien ne va plus */ -	if (!plane->state->crtc || !plane->state->fb) +	if (!new_state->crtc || !new_state->fb)  		return; -	if (!plane->state->visible) { -		tegra_shared_plane_atomic_disable(plane, old_state); +	if (!new_state->visible) { +		tegra_shared_plane_atomic_disable(plane, state);  		return;  	} @@ -477,22 +501,32 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,  	/* disable compression */  	tegra_plane_writel(p, 0, DC_WINBUF_CDE_CONTROL); -	base = state->iova[0] + fb->offsets[0]; +	base = tegra_plane_state->iova[0] + fb->offsets[0]; + +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT +	/* +	 * Physical address bit 39 in Tegra194 is used as a switch for special +	 * logic that swizzles the memory using either the legacy Tegra or the +	 * dGPU sector layout. +	 */ +	if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU) +		base |= BIT_ULL(39); +#endif -	tegra_plane_writel(p, state->format, DC_WIN_COLOR_DEPTH); +	tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH);  	tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS); -	value = V_POSITION(plane->state->crtc_y) | -		H_POSITION(plane->state->crtc_x); +	value = V_POSITION(new_state->crtc_y) | +		H_POSITION(new_state->crtc_x);  	tegra_plane_writel(p, value, DC_WIN_POSITION); -	value = V_SIZE(plane->state->crtc_h) | H_SIZE(plane->state->crtc_w); +	value = V_SIZE(new_state->crtc_h) | H_SIZE(new_state->crtc_w);  	tegra_plane_writel(p, value, DC_WIN_SIZE);  	value = WIN_ENABLE | COLOR_EXPAND;  	tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS); -	value = V_SIZE(plane->state->crtc_h) | H_SIZE(plane->state->crtc_w); +	value = V_SIZE(new_state->crtc_h) | H_SIZE(new_state->crtc_w);  	tegra_plane_writel(p, value, DC_WIN_CROPPED_SIZE);  	tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI); @@ -504,15 +538,15 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,  	value = CLAMP_BEFORE_BLEND | DEGAMMA_SRGB | INPUT_RANGE_FULL;  	tegra_plane_writel(p, value, DC_WIN_SET_PARAMS); -	value = OFFSET_X(plane->state->src_y >> 16) | -		OFFSET_Y(plane->state->src_x >> 16); +	value = OFFSET_X(new_state->src_y >> 16) | +		OFFSET_Y(new_state->src_x >> 16);  	tegra_plane_writel(p, value, DC_WINBUF_CROPPED_POINT);  	if (dc->soc->supports_block_linear) { -		unsigned long height = state->tiling.value; +		unsigned long height = tegra_plane_state->tiling.value;  		/* XXX */ -		switch (state->tiling.mode) { +		switch (tegra_plane_state->tiling.mode) {  		case TEGRA_BO_TILING_MODE_PITCH:  			value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(0) |  				DC_WINBUF_SURFACE_KIND_PITCH; @@ -556,9 +590,8 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm,  	enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;  	struct tegra_drm *tegra = drm->dev_private;  	struct tegra_display_hub *hub = tegra->hub; -	/* planes can be assigned to arbitrary CRTCs */ -	unsigned int possible_crtcs = 0x7;  	struct tegra_shared_plane *plane; +	unsigned int possible_crtcs;  	unsigned int num_formats;  	const u64 *modifiers;  	struct drm_plane *p; @@ -577,6 +610,9 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm,  	p = &plane->base.base; +	/* planes can be assigned to arbitrary CRTCs */ +	possible_crtcs = BIT(tegra->num_crtcs) - 1; +  	num_formats = ARRAY_SIZE(tegra_shared_plane_formats);  	formats = tegra_shared_plane_formats;  	modifiers = tegra_shared_plane_modifiers; @@ -842,12 +878,19 @@ static const struct host1x_client_ops tegra_display_hub_ops = {  static int tegra_display_hub_probe(struct platform_device *pdev)  { +	u64 dma_mask = dma_get_mask(pdev->dev.parent);  	struct device_node *child = NULL;  	struct tegra_display_hub *hub;  	struct clk *clk;  	unsigned int i;  	int err; +	err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask); +	if (err < 0) { +		dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err); +		return err; +	} +  	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);  	if (!hub)  		return -ENOMEM; | 
