Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19c800ca authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm/tegra/for-4.17-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next

drm/tegra: Changes for v4.17-rc1

This fixes mmap() for fbdev devices by providing a custom implementation
based on the KMS variant. This is a fairly exotic case these days, hence
why it is not flagged for stable.

There is also support for dedicating one of the overlay planes to serve
as a hardware cursor on older Tegra that did support hardware cursors
but not RGBA formats for it.

Planes will now also export the IN_FORMATS property by supporting the
various block-linear tiling modifiers for RGBA pixel formats.

Other than that, there's a bit of cleanup of DMA API abuse, use of the
private object infrastructure for global state (rather than subclassing
atomic state objects) and an implementation of ->{begin,end}_cpu_access
callbacks for PRIME exported buffers, which allow users to perform cache
maintenance on these buffers.

* tag 'drm/tegra/for-4.17-rc1' of git://anongit.freedesktop.org/tegra/linux:
  drm/tegra: prime: Implement ->{begin,end}_cpu_access()
  drm/tegra: gem: Map pages via the DMA API
  drm/tegra: hub: Use private object for global state
  drm/tegra: fb: Properly support linear modifier
  drm/tegra: plane: Support format modifiers
  drm/tegra: dc: Dedicate overlay plane to cursor on older Tegra's
  drm/tegra: plane: Make tegra_plane_get_overlap_index() static
  drm/tegra: fb: Implement ->fb_mmap() callback
  drm/tegra: gem: Make __tegra_gem_mmap() available more widely
  drm/tegra: gem: Reshuffle declarations
parents 4f6dd8d6 27e92f1f
Loading
Loading
Loading
Loading
+50 −32
Original line number Diff line number Diff line
@@ -383,6 +383,12 @@ static const u32 tegra20_primary_formats[] = {
	DRM_FORMAT_XRGB8888,
};

static const u64 tegra20_modifiers[] = {
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED,
	DRM_FORMAT_MOD_INVALID
};

static const u32 tegra114_primary_formats[] = {
	DRM_FORMAT_ARGB4444,
	DRM_FORMAT_ARGB1555,
@@ -430,6 +436,17 @@ static const u32 tegra124_primary_formats[] = {
	DRM_FORMAT_BGRX8888,
};

static const u64 tegra124_modifiers[] = {
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
	DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
	DRM_FORMAT_MOD_INVALID
};

static int tegra_plane_atomic_check(struct drm_plane *plane,
				    struct drm_plane_state *state)
{
@@ -596,6 +613,7 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
	enum drm_plane_type type = DRM_PLANE_TYPE_PRIMARY;
	struct tegra_plane *plane;
	unsigned int num_formats;
	const u64 *modifiers;
	const u32 *formats;
	int err;

@@ -610,10 +628,11 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,

	num_formats = dc->soc->num_primary_formats;
	formats = dc->soc->primary_formats;
	modifiers = dc->soc->modifiers;

	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
				       &tegra_plane_funcs, formats,
				       num_formats, NULL, type, NULL);
				       num_formats, modifiers, type, NULL);
	if (err < 0) {
		kfree(plane);
		return ERR_PTR(err);
@@ -864,11 +883,13 @@ static const u32 tegra124_overlay_formats[] = {

static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
						       struct tegra_dc *dc,
						       unsigned int index)
						       unsigned int index,
						       bool cursor)
{
	unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm);
	struct tegra_plane *plane;
	unsigned int num_formats;
	enum drm_plane_type type;
	const u32 *formats;
	int err;

@@ -883,10 +904,14 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
	num_formats = dc->soc->num_overlay_formats;
	formats = dc->soc->overlay_formats;

	if (!cursor)
		type = DRM_PLANE_TYPE_OVERLAY;
	else
		type = DRM_PLANE_TYPE_CURSOR;

	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
				       &tegra_plane_funcs, formats,
				       num_formats, NULL,
				       DRM_PLANE_TYPE_OVERLAY, NULL);
				       num_formats, NULL, type, NULL);
	if (err < 0) {
		kfree(plane);
		return ERR_PTR(err);
@@ -938,6 +963,7 @@ static struct drm_plane *tegra_dc_add_planes(struct drm_device *drm,
					     struct tegra_dc *dc)
{
	struct drm_plane *planes[2], *primary;
	unsigned int planes_num;
	unsigned int i;
	int err;

@@ -945,8 +971,14 @@ static struct drm_plane *tegra_dc_add_planes(struct drm_device *drm,
	if (IS_ERR(primary))
		return primary;

	for (i = 0; i < 2; i++) {
		planes[i] = tegra_dc_overlay_plane_create(drm, dc, 1 + i);
	if (dc->soc->supports_cursor)
		planes_num = 2;
	else
		planes_num = 1;

	for (i = 0; i < planes_num; i++) {
		planes[i] = tegra_dc_overlay_plane_create(drm, dc, 1 + i,
							  false);
		if (IS_ERR(planes[i])) {
			err = PTR_ERR(planes[i]);

@@ -1704,31 +1736,6 @@ static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
	drm_crtc_vblank_on(crtc);
}

static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
				   struct drm_crtc_state *state)
{
	struct tegra_atomic_state *s = to_tegra_atomic_state(state->state);
	struct tegra_dc_state *tegra = to_dc_state(state);

	/*
	 * The display hub display clock needs to be fed by the display clock
	 * with the highest frequency to ensure proper functioning of all the
	 * displays.
	 *
	 * Note that this isn't used before Tegra186, but it doesn't hurt and
	 * conditionalizing it would make the code less clean.
	 */
	if (state->active) {
		if (!s->clk_disp || tegra->pclk > s->rate) {
			s->dc = to_tegra_dc(crtc);
			s->clk_disp = s->dc->clk;
			s->rate = tegra->pclk;
		}
	}

	return 0;
}

static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
				    struct drm_crtc_state *old_crtc_state)
{
@@ -1765,7 +1772,6 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
}

static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
	.atomic_check = tegra_crtc_atomic_check,
	.atomic_begin = tegra_crtc_atomic_begin,
	.atomic_flush = tegra_crtc_atomic_flush,
	.atomic_enable = tegra_crtc_atomic_enable,
@@ -1864,6 +1870,13 @@ static int tegra_dc_init(struct host1x_client *client)
			err = PTR_ERR(cursor);
			goto cleanup;
		}
	} else {
		/* dedicate one overlay to mouse cursor */
		cursor = tegra_dc_overlay_plane_create(drm, dc, 2, true);
		if (IS_ERR(cursor)) {
			err = PTR_ERR(cursor);
			goto cleanup;
		}
	}

	err = drm_crtc_init_with_planes(drm, &dc->base, primary, cursor,
@@ -1954,6 +1967,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
	.primary_formats = tegra20_primary_formats,
	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
	.overlay_formats = tegra20_overlay_formats,
	.modifiers = tegra20_modifiers,
};

static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -1970,6 +1984,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
	.primary_formats = tegra20_primary_formats,
	.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
	.overlay_formats = tegra20_overlay_formats,
	.modifiers = tegra20_modifiers,
};

static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -1986,6 +2001,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
	.primary_formats = tegra114_primary_formats,
	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
	.overlay_formats = tegra114_overlay_formats,
	.modifiers = tegra20_modifiers,
};

static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -2002,6 +2018,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
	.primary_formats = tegra114_primary_formats,
	.num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats),
	.overlay_formats = tegra114_overlay_formats,
	.modifiers = tegra124_modifiers,
};

static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
@@ -2018,6 +2035,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
	.primary_formats = tegra114_primary_formats,
	.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
	.overlay_formats = tegra114_overlay_formats,
	.modifiers = tegra124_modifiers,
};

static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ struct tegra_dc_soc_info {
	unsigned int num_primary_formats;
	const u32 *overlay_formats;
	unsigned int num_overlay_formats;
	const u64 *modifiers;
};

struct tegra_dc {
+4 −32
Original line number Diff line number Diff line
@@ -42,6 +42,10 @@ static int tegra_atomic_check(struct drm_device *drm,
	if (err < 0)
		return err;

	err = tegra_display_hub_atomic_check(drm, state);
	if (err < 0)
		return err;

	err = drm_atomic_normalize_zpos(drm, state);
	if (err < 0)
		return err;
@@ -56,35 +60,6 @@ static int tegra_atomic_check(struct drm_device *drm,
	return 0;
}

static struct drm_atomic_state *
tegra_atomic_state_alloc(struct drm_device *drm)
{
	struct tegra_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL);

	if (!state || drm_atomic_state_init(drm, &state->base) < 0) {
		kfree(state);
		return NULL;
	}

	return &state->base;
}

static void tegra_atomic_state_clear(struct drm_atomic_state *state)
{
	struct tegra_atomic_state *tegra = to_tegra_atomic_state(state);

	drm_atomic_state_default_clear(state);
	tegra->clk_disp = NULL;
	tegra->dc = NULL;
	tegra->rate = 0;
}

static void tegra_atomic_state_free(struct drm_atomic_state *state)
{
	drm_atomic_state_default_release(state);
	kfree(state);
}

static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
	.fb_create = tegra_fb_create,
#ifdef CONFIG_DRM_FBDEV_EMULATION
@@ -92,9 +67,6 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
#endif
	.atomic_check = tegra_atomic_check,
	.atomic_commit = drm_atomic_helper_commit,
	.atomic_state_alloc = tegra_atomic_state_alloc,
	.atomic_state_clear = tegra_atomic_state_clear,
	.atomic_state_free = tegra_atomic_state_free,
};

static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
+0 −14
Original line number Diff line number Diff line
@@ -42,20 +42,6 @@ struct tegra_fbdev {
};
#endif

struct tegra_atomic_state {
	struct drm_atomic_state base;

	struct clk *clk_disp;
	struct tegra_dc *dc;
	unsigned long rate;
};

static inline struct tegra_atomic_state *
to_tegra_atomic_state(struct drm_atomic_state *state)
{
	return container_of(state, struct tegra_atomic_state, base);
}

struct tegra_drm {
	struct drm_device *drm;

+22 −3
Original line number Diff line number Diff line
@@ -55,6 +55,11 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
	uint64_t modifier = fb->base.modifier;

	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
		tiling->mode = TEGRA_BO_TILING_MODE_PITCH;
		tiling->value = 0;
		break;

	case DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED:
		tiling->mode = TEGRA_BO_TILING_MODE_TILED;
		tiling->value = 0;
@@ -91,9 +96,7 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
		break;

	default:
		/* TODO: handle YUV formats? */
		*tiling = fb->planes[0]->tiling;
		break;
		return -EINVAL;
	}

	return 0;
@@ -224,12 +227,28 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
}

#ifdef CONFIG_DRM_FBDEV_EMULATION
static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
	struct drm_fb_helper *helper = info->par;
	struct tegra_bo *bo;
	int err;

	bo = tegra_fb_get_plane(helper->fb, 0);

	err = drm_gem_mmap_obj(&bo->gem, bo->gem.size, vma);
	if (err < 0)
		return err;

	return __tegra_gem_mmap(&bo->gem, vma);
}

static struct fb_ops tegra_fb_ops = {
	.owner = THIS_MODULE,
	DRM_FB_HELPER_DEFAULT_OPS,
	.fb_fillrect = drm_fb_helper_sys_fillrect,
	.fb_copyarea = drm_fb_helper_sys_copyarea,
	.fb_imageblit = drm_fb_helper_sys_imageblit,
	.fb_mmap = tegra_fb_mmap,
};

static int tegra_fbdev_probe(struct drm_fb_helper *helper,
Loading