Commit 5acd3514 authored by Thierry Reding's avatar Thierry Reding

drm/tegra: Move common plane code to separate file

Subsequent patches will add support for Tegra186 which has a different
architecture and needs different plane code but which can share a lot of
code with earlier Tegra support.
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent b1415ff2
......@@ -5,6 +5,7 @@ tegra-drm-y := \
drm.o \
gem.o \
fb.o \
plane.o \
dc.o \
output.o \
rgb.o \
......
......@@ -19,38 +19,12 @@
#include "dc.h"
#include "drm.h"
#include "gem.h"
#include "plane.h"
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
struct tegra_plane {
struct drm_plane base;
unsigned int index;
};
static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
{
return container_of(plane, struct tegra_plane, base);
}
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;
}
static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)
{
stats->frames = 0;
......@@ -97,81 +71,6 @@ void tegra_dc_commit(struct tegra_dc *dc)
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
}
static int tegra_dc_format(u32 fourcc, u32 *format, u32 *swap)
{
/* assume no swapping of fetched data */
if (swap)
*swap = BYTE_SWAP_NOSWAP;
switch (fourcc) {
case DRM_FORMAT_XBGR8888:
*format = WIN_COLOR_DEPTH_R8G8B8A8;
break;
case DRM_FORMAT_XRGB8888:
*format = WIN_COLOR_DEPTH_B8G8R8A8;
break;
case DRM_FORMAT_RGB565:
*format = WIN_COLOR_DEPTH_B5G6R5;
break;
case DRM_FORMAT_UYVY:
*format = WIN_COLOR_DEPTH_YCbCr422;
break;
case DRM_FORMAT_YUYV:
if (swap)
*swap = BYTE_SWAP_SWAP2;
*format = WIN_COLOR_DEPTH_YCbCr422;
break;
case DRM_FORMAT_YUV420:
*format = WIN_COLOR_DEPTH_YCbCr420P;
break;
case DRM_FORMAT_YUV422:
*format = WIN_COLOR_DEPTH_YCbCr422P;
break;
default:
return -EINVAL;
}
return 0;
}
static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
{
switch (format) {
case WIN_COLOR_DEPTH_YCbCr422:
case WIN_COLOR_DEPTH_YUV422:
if (planar)
*planar = false;
return true;
case WIN_COLOR_DEPTH_YCbCr420P:
case WIN_COLOR_DEPTH_YUV420P:
case WIN_COLOR_DEPTH_YCbCr422P:
case WIN_COLOR_DEPTH_YUV422P:
case WIN_COLOR_DEPTH_YCbCr422R:
case WIN_COLOR_DEPTH_YUV422R:
case WIN_COLOR_DEPTH_YCbCr422RA:
case WIN_COLOR_DEPTH_YUV422RA:
if (planar)
*planar = true;
return true;
}
if (planar)
*planar = false;
return false;
}
static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
unsigned int bpp)
{
......@@ -223,7 +122,7 @@ static void tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
* For YUV planar modes, the number of bytes per pixel takes into
* account only the luma component and therefore is 1.
*/
yuv = tegra_dc_format_is_yuv(window->format, &planar);
yuv = tegra_plane_format_is_yuv(window->format, &planar);
if (!yuv)
bpp = window->bits_per_pixel / 8;
else
......@@ -385,101 +284,12 @@ static void tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
spin_unlock_irqrestore(&dc->lock, flags);
}
static void tegra_plane_destroy(struct drm_plane *plane)
{
struct tegra_plane *p = to_tegra_plane(plane);
drm_plane_cleanup(plane);
kfree(p);
}
static const u32 tegra_primary_plane_formats[] = {
DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_RGB565,
};
static void tegra_plane_reset(struct drm_plane *plane)
{
struct tegra_plane_state *state;
if (plane->state)
__drm_atomic_helper_plane_destroy_state(plane->state);
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 = kmalloc(sizeof(*copy), GFP_KERNEL);
if (!copy)
return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
copy->tiling = state->tiling;
copy->format = state->format;
copy->swap = state->swap;
return &copy->base;
}
static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
__drm_atomic_helper_plane_destroy_state(state);
kfree(state);
}
static const struct drm_plane_funcs tegra_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = tegra_plane_destroy,
.reset = tegra_plane_reset,
.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
.atomic_destroy_state = tegra_plane_atomic_destroy_state,
};
static int tegra_plane_state_add(struct tegra_plane *plane,
struct drm_plane_state *state)
{
struct drm_crtc_state *crtc_state;
struct tegra_dc_state *tegra;
struct drm_rect clip;
int err;
/* Propagate errors from allocation or locking failures. */
crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
clip.x1 = 0;
clip.y1 = 0;
clip.x2 = crtc_state->mode.hdisplay;
clip.y2 = crtc_state->mode.vdisplay;
/* Check plane state for visibility and calculate clipping bounds */
err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
0, INT_MAX, true, true);
if (err < 0)
return err;
tegra = to_dc_state(crtc_state);
tegra->planes |= WIN_A_ACT_REQ << plane->index;
return 0;
}
static int tegra_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
......@@ -493,8 +303,9 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
if (!state->crtc)
return 0;
err = tegra_dc_format(state->fb->format->format, &plane_state->format,
&plane_state->swap);
err = tegra_plane_format(state->fb->format->format,
&plane_state->format,
&plane_state->swap);
if (err < 0)
return err;
......
/*
* Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include "dc.h"
#include "plane.h"
static void tegra_plane_destroy(struct drm_plane *plane)
{
struct tegra_plane *p = to_tegra_plane(plane);
drm_plane_cleanup(plane);
kfree(p);
}
static void tegra_plane_reset(struct drm_plane *plane)
{
struct tegra_plane_state *state;
if (plane->state)
__drm_atomic_helper_plane_destroy_state(plane->state);
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 = kmalloc(sizeof(*copy), GFP_KERNEL);
if (!copy)
return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
copy->tiling = state->tiling;
copy->format = state->format;
copy->swap = state->swap;
return &copy->base;
}
static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
__drm_atomic_helper_plane_destroy_state(state);
kfree(state);
}
const struct drm_plane_funcs tegra_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = tegra_plane_destroy,
.reset = tegra_plane_reset,
.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
.atomic_destroy_state = tegra_plane_atomic_destroy_state,
};
int tegra_plane_state_add(struct tegra_plane *plane,
struct drm_plane_state *state)
{
struct drm_crtc_state *crtc_state;
struct tegra_dc_state *tegra;
struct drm_rect clip;
int err;
/* Propagate errors from allocation or locking failures. */
crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
clip.x1 = 0;
clip.y1 = 0;
clip.x2 = crtc_state->mode.hdisplay;
clip.y2 = crtc_state->mode.vdisplay;
/* Check plane state for visibility and calculate clipping bounds */
err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
0, INT_MAX, true, true);
if (err < 0)
return err;
tegra = to_dc_state(crtc_state);
tegra->planes |= WIN_A_ACT_REQ << plane->index;
return 0;
}
int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
{
/* assume no swapping of fetched data */
if (swap)
*swap = BYTE_SWAP_NOSWAP;
switch (fourcc) {
case DRM_FORMAT_XBGR8888:
*format = WIN_COLOR_DEPTH_R8G8B8A8;
break;
case DRM_FORMAT_XRGB8888:
*format = WIN_COLOR_DEPTH_B8G8R8A8;
break;
case DRM_FORMAT_RGB565:
*format = WIN_COLOR_DEPTH_B5G6R5;
break;
case DRM_FORMAT_UYVY:
*format = WIN_COLOR_DEPTH_YCbCr422;
break;
case DRM_FORMAT_YUYV:
if (!swap)
return -EINVAL;
*format = WIN_COLOR_DEPTH_YCbCr422;
*swap = BYTE_SWAP_SWAP2;
break;
case DRM_FORMAT_YUV420:
*format = WIN_COLOR_DEPTH_YCbCr420P;
break;
case DRM_FORMAT_YUV422:
*format = WIN_COLOR_DEPTH_YCbCr422P;
break;
default:
return -EINVAL;
}
return 0;
}
bool tegra_plane_format_is_yuv(unsigned int format, bool *planar)
{
switch (format) {
case WIN_COLOR_DEPTH_YCbCr422:
case WIN_COLOR_DEPTH_YUV422:
if (planar)
*planar = false;
return true;
case WIN_COLOR_DEPTH_YCbCr420P:
case WIN_COLOR_DEPTH_YUV420P:
case WIN_COLOR_DEPTH_YCbCr422P:
case WIN_COLOR_DEPTH_YUV422P:
case WIN_COLOR_DEPTH_YCbCr422R:
case WIN_COLOR_DEPTH_YUV422R:
case WIN_COLOR_DEPTH_YCbCr422RA:
case WIN_COLOR_DEPTH_YUV422RA:
if (planar)
*planar = true;
return true;
}
if (planar)
*planar = false;
return false;
}
/*
* Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef TEGRA_PLANE_H
#define TEGRA_PLANE_H 1
#include <drm/drm_plane.h>
struct tegra_bo;
struct tegra_plane {
struct drm_plane base;
unsigned int index;
};
struct tegra_cursor {
struct tegra_plane base;
struct tegra_bo *bo;
unsigned int width;
unsigned int height;
};
static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
{
return container_of(plane, struct tegra_plane, base);
}
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;
}
extern const struct drm_plane_funcs tegra_plane_funcs;
int tegra_plane_state_add(struct tegra_plane *plane,
struct drm_plane_state *state);
int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap);
bool tegra_plane_format_is_yuv(unsigned int format, bool *planar);
#endif /* TEGRA_PLANE_H */
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