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

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
...@@ -59,6 +59,23 @@ static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 = { ...@@ -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 = { ...@@ -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[] = {
......
...@@ -170,13 +170,13 @@ struct tegra_dc_window { ...@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment