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

Commit 8f604f8c authored by Thierry Reding's avatar Thierry Reding
Browse files

drm/tegra: Track tiling and format in plane state



Tracking these in the plane state allows them to be computed in the
->atomic_check() callback and reused when applying the configuration in
->atomic_update().

Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 47802b09
Loading
Loading
Loading
Loading
+99 −28
Original line number Original line Diff line number Diff line
@@ -59,6 +59,23 @@ static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)
	return NULL;
	return NULL;
}
}


struct tegra_plane_state {
	struct drm_plane_state base;

	struct tegra_bo_tiling tiling;
	u32 format;
	u32 swap;
};

static inline struct tegra_plane_state *
to_tegra_plane_state(struct drm_plane_state *state)
{
	if (state)
		return container_of(state, struct tegra_plane_state, base);

	return NULL;
}

/*
/*
 * Reads the active copy of a register. This takes the dc->lock spinlock to
 * Reads the active copy of a register. This takes the dc->lock spinlock to
 * prevent races with the VBLANK processing which also needs access to the
 * prevent races with the VBLANK processing which also needs access to the
@@ -97,43 +114,49 @@ void tegra_dc_commit(struct tegra_dc *dc)
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
}
}


static unsigned int tegra_dc_format(uint32_t format, uint32_t *swap)
static int tegra_dc_format(u32 fourcc, u32 *format, u32 *swap)
{
{
	/* assume no swapping of fetched data */
	/* assume no swapping of fetched data */
	if (swap)
	if (swap)
		*swap = BYTE_SWAP_NOSWAP;
		*swap = BYTE_SWAP_NOSWAP;


	switch (format) {
	switch (fourcc) {
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_XBGR8888:
		return WIN_COLOR_DEPTH_R8G8B8A8;
		*format = WIN_COLOR_DEPTH_R8G8B8A8;
		break;


	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XRGB8888:
		return WIN_COLOR_DEPTH_B8G8R8A8;
		*format = WIN_COLOR_DEPTH_B8G8R8A8;
		break;


	case DRM_FORMAT_RGB565:
	case DRM_FORMAT_RGB565:
		return WIN_COLOR_DEPTH_B5G6R5;
		*format = WIN_COLOR_DEPTH_B5G6R5;
		break;


	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_UYVY:
		return WIN_COLOR_DEPTH_YCbCr422;
		*format = WIN_COLOR_DEPTH_YCbCr422;
		break;


	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YUYV:
		if (swap)
		if (swap)
			*swap = BYTE_SWAP_SWAP2;
			*swap = BYTE_SWAP_SWAP2;


		return WIN_COLOR_DEPTH_YCbCr422;
		*format = WIN_COLOR_DEPTH_YCbCr422;
		break;


	case DRM_FORMAT_YUV420:
	case DRM_FORMAT_YUV420:
		return WIN_COLOR_DEPTH_YCbCr420P;
		*format = WIN_COLOR_DEPTH_YCbCr420P;
		break;


	case DRM_FORMAT_YUV422:
	case DRM_FORMAT_YUV422:
		return WIN_COLOR_DEPTH_YCbCr422P;
		*format = WIN_COLOR_DEPTH_YCbCr422P;
		break;


	default:
	default:
		break;
		return -EINVAL;
	}
	}


	WARN(1, "unsupported pixel format %u, using default\n", format);
	return 0;
	return WIN_COLOR_DEPTH_B8G8R8A8;
}
}


static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
@@ -398,13 +421,54 @@ static void tegra_primary_plane_destroy(struct drm_plane *plane)
	tegra_plane_destroy(plane);
	tegra_plane_destroy(plane);
}
}


static void tegra_plane_reset(struct drm_plane *plane)
{
	struct tegra_plane_state *state;

	if (plane->state && plane->state->fb)
		drm_framebuffer_unreference(plane->state->fb);

	kfree(plane->state);
	plane->state = NULL;

	state = kzalloc(sizeof(*state), GFP_KERNEL);
	if (state) {
		plane->state = &state->base;
		plane->state->plane = plane;
	}
}

static struct drm_plane_state *tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
{
	struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
	struct tegra_plane_state *copy;

	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
	if (!copy)
		return NULL;

	if (copy->base.fb)
		drm_framebuffer_reference(copy->base.fb);

	return &copy->base;
}

static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
					     struct drm_plane_state *state)
{
	if (state->fb)
		drm_framebuffer_unreference(state->fb);

	kfree(state);
}

static const struct drm_plane_funcs tegra_primary_plane_funcs = {
static const struct drm_plane_funcs tegra_primary_plane_funcs = {
	.update_plane = drm_atomic_helper_update_plane,
	.update_plane = drm_atomic_helper_update_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.destroy = tegra_primary_plane_destroy,
	.destroy = tegra_primary_plane_destroy,
	.reset = drm_atomic_helper_plane_reset,
	.reset = tegra_plane_reset,
	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
};
};


static int tegra_plane_prepare_fb(struct drm_plane *plane,
static int tegra_plane_prepare_fb(struct drm_plane *plane,
@@ -439,20 +503,26 @@ static int tegra_plane_state_add(struct tegra_plane *plane,
static int tegra_plane_atomic_check(struct drm_plane *plane,
static int tegra_plane_atomic_check(struct drm_plane *plane,
				    struct drm_plane_state *state)
				    struct drm_plane_state *state)
{
{
	struct tegra_plane_state *plane_state = to_tegra_plane_state(state);
	struct tegra_bo_tiling *tiling = &plane_state->tiling;
	struct tegra_plane *tegra = to_tegra_plane(plane);
	struct tegra_plane *tegra = to_tegra_plane(plane);
	struct tegra_dc *dc = to_tegra_dc(state->crtc);
	struct tegra_dc *dc = to_tegra_dc(state->crtc);
	struct tegra_bo_tiling tiling;
	int err;
	int err;


	/* no need for further checks if the plane is being disabled */
	/* no need for further checks if the plane is being disabled */
	if (!state->crtc)
	if (!state->crtc)
		return 0;
		return 0;


	err = tegra_fb_get_tiling(state->fb, &tiling);
	err = tegra_dc_format(state->fb->pixel_format, &plane_state->format,
			      &plane_state->swap);
	if (err < 0)
		return err;

	err = tegra_fb_get_tiling(state->fb, tiling);
	if (err < 0)
	if (err < 0)
		return err;
		return err;


	if (tiling.mode == TEGRA_BO_TILING_MODE_BLOCK &&
	if (tiling->mode == TEGRA_BO_TILING_MODE_BLOCK &&
	    !dc->soc->supports_block_linear) {
	    !dc->soc->supports_block_linear) {
		DRM_ERROR("hardware doesn't support block linear mode\n");
		DRM_ERROR("hardware doesn't support block linear mode\n");
		return -EINVAL;
		return -EINVAL;
@@ -480,12 +550,12 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
static void tegra_plane_atomic_update(struct drm_plane *plane,
static void tegra_plane_atomic_update(struct drm_plane *plane,
				      struct drm_plane_state *old_state)
				      struct drm_plane_state *old_state)
{
{
	struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
	struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
	struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
	struct drm_framebuffer *fb = plane->state->fb;
	struct drm_framebuffer *fb = plane->state->fb;
	struct tegra_plane *p = to_tegra_plane(plane);
	struct tegra_plane *p = to_tegra_plane(plane);
	struct tegra_dc_window window;
	struct tegra_dc_window window;
	unsigned int i;
	unsigned int i;
	int err;


	/* rien ne va plus */
	/* rien ne va plus */
	if (!plane->state->crtc || !plane->state->fb)
	if (!plane->state->crtc || !plane->state->fb)
@@ -500,12 +570,13 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
	window.dst.y = plane->state->crtc_y;
	window.dst.y = plane->state->crtc_y;
	window.dst.w = plane->state->crtc_w;
	window.dst.w = plane->state->crtc_w;
	window.dst.h = plane->state->crtc_h;
	window.dst.h = plane->state->crtc_h;
	window.format = tegra_dc_format(fb->pixel_format, &window.swap);
	window.bits_per_pixel = fb->bits_per_pixel;
	window.bits_per_pixel = fb->bits_per_pixel;
	window.bottom_up = tegra_fb_is_bottom_up(fb);
	window.bottom_up = tegra_fb_is_bottom_up(fb);


	err = tegra_fb_get_tiling(fb, &window.tiling);
	/* copy from state */
	WARN_ON(err < 0);
	window.tiling = state->tiling;
	window.format = state->format;
	window.swap = state->swap;


	for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
	for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
		struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
		struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
@@ -710,9 +781,9 @@ static const struct drm_plane_funcs tegra_cursor_plane_funcs = {
	.update_plane = drm_atomic_helper_update_plane,
	.update_plane = drm_atomic_helper_update_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.destroy = tegra_plane_destroy,
	.destroy = tegra_plane_destroy,
	.reset = drm_atomic_helper_plane_reset,
	.reset = tegra_plane_reset,
	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
};
};


static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {
static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {
@@ -767,9 +838,9 @@ static const struct drm_plane_funcs tegra_overlay_plane_funcs = {
	.update_plane = drm_atomic_helper_update_plane,
	.update_plane = drm_atomic_helper_update_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.disable_plane = drm_atomic_helper_disable_plane,
	.destroy = tegra_overlay_plane_destroy,
	.destroy = tegra_overlay_plane_destroy,
	.reset = drm_atomic_helper_plane_reset,
	.reset = tegra_plane_reset,
	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
};
};


static const uint32_t tegra_overlay_plane_formats[] = {
static const uint32_t tegra_overlay_plane_formats[] = {
+2 −2
Original line number Original line Diff line number Diff line
@@ -170,13 +170,13 @@ struct tegra_dc_window {
		unsigned int h;
		unsigned int h;
	} dst;
	} dst;
	unsigned int bits_per_pixel;
	unsigned int bits_per_pixel;
	unsigned int format;
	unsigned int swap;
	unsigned int stride[2];
	unsigned int stride[2];
	unsigned long base[3];
	unsigned long base[3];
	bool bottom_up;
	bool bottom_up;


	struct tegra_bo_tiling tiling;
	struct tegra_bo_tiling tiling;
	u32 format;
	u32 swap;
};
};


/* from dc.c */
/* from dc.c */