Mediatek DRM next for Linux 5.5 - 2
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJdw3RSAAoJEOHKc6PJWU4kB04P+gOyl1YV1p0h9N4Wstxn/RdK TbK8Gt4u+vSa7PtiFUwmanbo4Af3VlMu34nbFanTn9P2QIRifh//gWLCZJnn2SkR ZXFimh3AxtMgox3FozucLzMNcb5bsHHscBNw88Gc3j9/nFMsZjdcppAlPYkOt+uq VqcPUOWAsbI4iEtl15Mf+oL6QeLAjPpDjOzZV1moUe08Ns2xy1bKGzq3UOD1OXmx 0gKJq6Qh5i1k/t2oZ3gMpfTzU4fgAjT8k60N5kbeGt3/wpem234YKVcy1FUKxSiH sxc6f8oJm5FEmS7hlvMPvfAcs0DzhrRzcQGiGVHBNXabj783gd9Jc5zNIZ4KCNEV U9W40DTbpA59u+nMY3hu1Gw9Pk/myuUbtWJFah5XlpL323wsFutvb0wcu6DV3f71 u7oIBKrf0Ije/h5B9s6aZsLNpzA+9pJPzeez5dAQ5eC3Bi/ZfWuwxUbP2yhZ5ZO7 BVTGMkHaYBXkVhFBS3NyyXvY8RNap+JechkOVJYH5KNWXAZk/4wS+PKcf9dychYx Js0OW4wvkXIX2ZKyI0bEH99HlFuwMeBvxqFCxd+zBdEScOcDtHX9cEDkUdBoQod7 8WrjlEnotIeX/U5EHJs+/QSnd24/bYFpoauetrfZwq7dE2y1zF7UW8w7/UstfyOU aNa1iBuoYFHz0QctDHNK =SjCW -----END PGP SIGNATURE----- Merge tag 'mediatek-drm-next-5.5-2' of https://github.com/ckhu-mediatek/linux.git-tags into drm-next Mediatek DRM next for Linux 5.5 - 2 Signed-off-by: Dave Airlie <airlied@redhat.com> From: CK Hu <ck.hu@mediatek.com> Link: https://patchwork.freedesktop.org/patch/msgid/1573093419.13645.5.camel@mtksdaap41
This commit is contained in:
commit
393fdfdb4a
@ -3,6 +3,8 @@
|
||||
* Copyright (c) 2015 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/module.h>
|
||||
@ -50,6 +52,8 @@
|
||||
OVL_CON_CLRFMT_RGB : 0)
|
||||
#define OVL_CON_AEN BIT(8)
|
||||
#define OVL_CON_ALPHA 0xff
|
||||
#define OVL_CON_VIRT_FLIP BIT(9)
|
||||
#define OVL_CON_HORZ_FLIP BIT(10)
|
||||
|
||||
struct mtk_disp_ovl_data {
|
||||
unsigned int addr;
|
||||
@ -137,6 +141,40 @@ static unsigned int mtk_ovl_layer_nr(struct mtk_ddp_comp *comp)
|
||||
return ovl->data->layer_nr;
|
||||
}
|
||||
|
||||
static unsigned int mtk_ovl_supported_rotations(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
return DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
|
||||
DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
|
||||
}
|
||||
|
||||
static int mtk_ovl_layer_check(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
struct mtk_plane_state *mtk_state)
|
||||
{
|
||||
struct drm_plane_state *state = &mtk_state->base;
|
||||
unsigned int rotation = 0;
|
||||
|
||||
rotation = drm_rotation_simplify(state->rotation,
|
||||
DRM_MODE_ROTATE_0 |
|
||||
DRM_MODE_REFLECT_X |
|
||||
DRM_MODE_REFLECT_Y);
|
||||
rotation &= ~DRM_MODE_ROTATE_0;
|
||||
|
||||
/* We can only do reflection, not rotation */
|
||||
if ((rotation & DRM_MODE_ROTATE_MASK) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* TODO: Rotating/reflecting YUV buffers is not supported at this time.
|
||||
* Only RGB[AX] variants are supported.
|
||||
*/
|
||||
if (state->fb->format->is_yuv && rotation != 0)
|
||||
return -EINVAL;
|
||||
|
||||
state->rotation = rotation;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx)
|
||||
{
|
||||
unsigned int reg;
|
||||
@ -229,6 +267,16 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
if (idx != 0)
|
||||
con |= OVL_CON_AEN | OVL_CON_ALPHA;
|
||||
|
||||
if (pending->rotation & DRM_MODE_REFLECT_Y) {
|
||||
con |= OVL_CON_VIRT_FLIP;
|
||||
addr += (pending->height - 1) * pending->pitch;
|
||||
}
|
||||
|
||||
if (pending->rotation & DRM_MODE_REFLECT_X) {
|
||||
con |= OVL_CON_HORZ_FLIP;
|
||||
addr += pending->pitch - 1;
|
||||
}
|
||||
|
||||
writel_relaxed(con, comp->regs + DISP_REG_OVL_CON(idx));
|
||||
writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
|
||||
writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
|
||||
@ -263,9 +311,11 @@ static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
|
||||
.stop = mtk_ovl_stop,
|
||||
.enable_vblank = mtk_ovl_enable_vblank,
|
||||
.disable_vblank = mtk_ovl_disable_vblank,
|
||||
.supported_rotations = mtk_ovl_supported_rotations,
|
||||
.layer_nr = mtk_ovl_layer_nr,
|
||||
.layer_on = mtk_ovl_layer_on,
|
||||
.layer_off = mtk_ovl_layer_off,
|
||||
.layer_check = mtk_ovl_layer_check,
|
||||
.layer_config = mtk_ovl_layer_config,
|
||||
.bgclr_in_on = mtk_ovl_bgclr_in_on,
|
||||
.bgclr_in_off = mtk_ovl_bgclr_in_off,
|
||||
|
@ -207,6 +207,28 @@ static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc)
|
||||
clk_disable_unprepare(mtk_crtc->ddp_comp[i]->clk);
|
||||
}
|
||||
|
||||
static
|
||||
struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
|
||||
struct drm_plane *plane,
|
||||
unsigned int *local_layer)
|
||||
{
|
||||
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
struct mtk_ddp_comp *comp;
|
||||
int i, count = 0;
|
||||
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
|
||||
comp = mtk_crtc->ddp_comp[i];
|
||||
if (plane->index < (count + mtk_ddp_comp_layer_nr(comp))) {
|
||||
*local_layer = plane->index - count;
|
||||
return comp;
|
||||
}
|
||||
count += mtk_ddp_comp_layer_nr(comp);
|
||||
}
|
||||
|
||||
WARN(1, "Failed to find component for plane %d\n", plane->index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
|
||||
{
|
||||
struct drm_crtc *crtc = &mtk_crtc->base;
|
||||
@ -283,19 +305,12 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
|
||||
for (i = 0; i < mtk_crtc->layer_nr; i++) {
|
||||
struct drm_plane *plane = &mtk_crtc->planes[i];
|
||||
struct mtk_plane_state *plane_state;
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
|
||||
unsigned int comp_layer_nr = mtk_ddp_comp_layer_nr(comp);
|
||||
struct mtk_ddp_comp *comp;
|
||||
unsigned int local_layer;
|
||||
|
||||
plane_state = to_mtk_plane_state(plane->state);
|
||||
|
||||
if (i >= comp_layer_nr) {
|
||||
comp = mtk_crtc->ddp_comp[1];
|
||||
local_layer = i - comp_layer_nr;
|
||||
} else
|
||||
local_layer = i;
|
||||
mtk_ddp_comp_layer_config(comp, local_layer,
|
||||
plane_state);
|
||||
comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer);
|
||||
mtk_ddp_comp_layer_config(comp, local_layer, plane_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -343,7 +358,6 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
|
||||
struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
|
||||
unsigned int i;
|
||||
unsigned int comp_layer_nr = mtk_ddp_comp_layer_nr(comp);
|
||||
unsigned int local_layer;
|
||||
|
||||
/*
|
||||
@ -366,22 +380,30 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
|
||||
|
||||
plane_state = to_mtk_plane_state(plane->state);
|
||||
|
||||
if (plane_state->pending.config) {
|
||||
if (i >= comp_layer_nr) {
|
||||
comp = mtk_crtc->ddp_comp[1];
|
||||
local_layer = i - comp_layer_nr;
|
||||
} else
|
||||
local_layer = i;
|
||||
if (!plane_state->pending.config)
|
||||
continue;
|
||||
|
||||
mtk_ddp_comp_layer_config(comp, local_layer,
|
||||
plane_state);
|
||||
plane_state->pending.config = false;
|
||||
}
|
||||
comp = mtk_drm_ddp_comp_for_plane(crtc, plane,
|
||||
&local_layer);
|
||||
|
||||
mtk_ddp_comp_layer_config(comp, local_layer,
|
||||
plane_state);
|
||||
plane_state->pending.config = false;
|
||||
}
|
||||
mtk_crtc->pending_planes = false;
|
||||
}
|
||||
}
|
||||
|
||||
int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
|
||||
struct mtk_plane_state *state)
|
||||
{
|
||||
unsigned int local_layer;
|
||||
struct mtk_ddp_comp *comp;
|
||||
|
||||
comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer);
|
||||
return mtk_ddp_comp_layer_check(comp, local_layer, state);
|
||||
}
|
||||
|
||||
static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state)
|
||||
{
|
||||
@ -543,14 +565,65 @@ void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp)
|
||||
mtk_drm_finish_page_flip(mtk_crtc);
|
||||
}
|
||||
|
||||
static int mtk_drm_crtc_num_comp_planes(struct mtk_drm_crtc *mtk_crtc,
|
||||
int comp_idx)
|
||||
{
|
||||
struct mtk_ddp_comp *comp;
|
||||
|
||||
if (comp_idx > 1)
|
||||
return 0;
|
||||
|
||||
comp = mtk_crtc->ddp_comp[comp_idx];
|
||||
if (!comp->funcs)
|
||||
return 0;
|
||||
|
||||
if (comp_idx == 1 && !comp->funcs->bgclr_in_on)
|
||||
return 0;
|
||||
|
||||
return mtk_ddp_comp_layer_nr(comp);
|
||||
}
|
||||
|
||||
static inline
|
||||
enum drm_plane_type mtk_drm_crtc_plane_type(unsigned int plane_idx)
|
||||
{
|
||||
if (plane_idx == 0)
|
||||
return DRM_PLANE_TYPE_PRIMARY;
|
||||
else if (plane_idx == 1)
|
||||
return DRM_PLANE_TYPE_CURSOR;
|
||||
else
|
||||
return DRM_PLANE_TYPE_OVERLAY;
|
||||
|
||||
}
|
||||
|
||||
static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev,
|
||||
struct mtk_drm_crtc *mtk_crtc,
|
||||
int comp_idx, int pipe)
|
||||
{
|
||||
int num_planes = mtk_drm_crtc_num_comp_planes(mtk_crtc, comp_idx);
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[comp_idx];
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < num_planes; i++) {
|
||||
ret = mtk_plane_init(drm_dev,
|
||||
&mtk_crtc->planes[mtk_crtc->layer_nr],
|
||||
BIT(pipe),
|
||||
mtk_drm_crtc_plane_type(mtk_crtc->layer_nr),
|
||||
mtk_ddp_comp_supported_rotations(comp));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mtk_crtc->layer_nr++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_drm_crtc_create(struct drm_device *drm_dev,
|
||||
const enum mtk_ddp_comp_id *path, unsigned int path_len)
|
||||
{
|
||||
struct mtk_drm_private *priv = drm_dev->dev_private;
|
||||
struct device *dev = drm_dev->dev;
|
||||
struct mtk_drm_crtc *mtk_crtc;
|
||||
enum drm_plane_type type;
|
||||
unsigned int zpos;
|
||||
unsigned int num_comp_planes = 0;
|
||||
int pipe = priv->num_pipes;
|
||||
int ret;
|
||||
int i;
|
||||
@ -606,23 +679,15 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
|
||||
mtk_crtc->ddp_comp[i] = comp;
|
||||
}
|
||||
|
||||
mtk_crtc->layer_nr = mtk_ddp_comp_layer_nr(mtk_crtc->ddp_comp[0]);
|
||||
if (mtk_crtc->ddp_comp_nr > 1) {
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[1];
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
|
||||
num_comp_planes += mtk_drm_crtc_num_comp_planes(mtk_crtc, i);
|
||||
|
||||
if (comp->funcs->bgclr_in_on)
|
||||
mtk_crtc->layer_nr += mtk_ddp_comp_layer_nr(comp);
|
||||
}
|
||||
mtk_crtc->planes = devm_kcalloc(dev, mtk_crtc->layer_nr,
|
||||
sizeof(struct drm_plane),
|
||||
GFP_KERNEL);
|
||||
mtk_crtc->planes = devm_kcalloc(dev, num_comp_planes,
|
||||
sizeof(struct drm_plane), GFP_KERNEL);
|
||||
|
||||
for (zpos = 0; zpos < mtk_crtc->layer_nr; zpos++) {
|
||||
type = (zpos == 0) ? DRM_PLANE_TYPE_PRIMARY :
|
||||
(zpos == 1) ? DRM_PLANE_TYPE_CURSOR :
|
||||
DRM_PLANE_TYPE_OVERLAY;
|
||||
ret = mtk_plane_init(drm_dev, &mtk_crtc->planes[zpos],
|
||||
BIT(pipe), type);
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
|
||||
ret = mtk_drm_crtc_init_comp_planes(drm_dev, mtk_crtc, i,
|
||||
pipe);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -19,5 +19,7 @@ void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp);
|
||||
int mtk_drm_crtc_create(struct drm_device *drm_dev,
|
||||
const enum mtk_ddp_comp_id *path,
|
||||
unsigned int path_len);
|
||||
int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
|
||||
struct mtk_plane_state *state);
|
||||
|
||||
#endif /* MTK_DRM_CRTC_H */
|
||||
|
@ -77,9 +77,13 @@ struct mtk_ddp_comp_funcs {
|
||||
void (*stop)(struct mtk_ddp_comp *comp);
|
||||
void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc);
|
||||
void (*disable_vblank)(struct mtk_ddp_comp *comp);
|
||||
unsigned int (*supported_rotations)(struct mtk_ddp_comp *comp);
|
||||
unsigned int (*layer_nr)(struct mtk_ddp_comp *comp);
|
||||
void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx);
|
||||
void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx);
|
||||
int (*layer_check)(struct mtk_ddp_comp *comp,
|
||||
unsigned int idx,
|
||||
struct mtk_plane_state *state);
|
||||
void (*layer_config)(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
struct mtk_plane_state *state);
|
||||
void (*gamma_set)(struct mtk_ddp_comp *comp,
|
||||
@ -130,6 +134,15 @@ static inline void mtk_ddp_comp_disable_vblank(struct mtk_ddp_comp *comp)
|
||||
comp->funcs->disable_vblank(comp);
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned int mtk_ddp_comp_supported_rotations(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->supported_rotations)
|
||||
return comp->funcs->supported_rotations(comp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->layer_nr)
|
||||
@ -152,6 +165,15 @@ static inline void mtk_ddp_comp_layer_off(struct mtk_ddp_comp *comp,
|
||||
comp->funcs->layer_off(comp, idx);
|
||||
}
|
||||
|
||||
static inline int mtk_ddp_comp_layer_check(struct mtk_ddp_comp *comp,
|
||||
unsigned int idx,
|
||||
struct mtk_plane_state *state)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->layer_check)
|
||||
return comp->funcs->layer_check(comp, idx, state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_layer_config(struct mtk_ddp_comp *comp,
|
||||
unsigned int idx,
|
||||
struct mtk_plane_state *state)
|
||||
|
@ -20,6 +20,12 @@
|
||||
static const u32 formats[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_BGRX8888,
|
||||
DRM_FORMAT_BGRA8888,
|
||||
DRM_FORMAT_ABGR8888,
|
||||
DRM_FORMAT_XBGR8888,
|
||||
DRM_FORMAT_RGB888,
|
||||
DRM_FORMAT_BGR888,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_UYVY,
|
||||
DRM_FORMAT_YUYV,
|
||||
@ -84,6 +90,7 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
|
||||
{
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int ret;
|
||||
|
||||
if (!fb)
|
||||
return 0;
|
||||
@ -91,6 +98,11 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
|
||||
if (!state->crtc)
|
||||
return 0;
|
||||
|
||||
ret = mtk_drm_crtc_plane_check(state->crtc, plane,
|
||||
to_mtk_plane_state(state));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
@ -132,6 +144,7 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
|
||||
state->pending.y = plane->state->dst.y1;
|
||||
state->pending.width = drm_rect_width(&plane->state->dst);
|
||||
state->pending.height = drm_rect_height(&plane->state->dst);
|
||||
state->pending.rotation = plane->state->rotation;
|
||||
wmb(); /* Make sure the above parameters are set before update */
|
||||
state->pending.dirty = true;
|
||||
}
|
||||
@ -154,7 +167,8 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
|
||||
};
|
||||
|
||||
int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
unsigned long possible_crtcs, enum drm_plane_type type)
|
||||
unsigned long possible_crtcs, enum drm_plane_type type,
|
||||
unsigned int supported_rotations)
|
||||
{
|
||||
int err;
|
||||
|
||||
@ -166,6 +180,14 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (supported_rotations & ~DRM_MODE_ROTATE_0) {
|
||||
err = drm_plane_create_rotation_property(plane,
|
||||
DRM_MODE_ROTATE_0,
|
||||
supported_rotations);
|
||||
if (err)
|
||||
DRM_INFO("Create rotation property failed\n");
|
||||
}
|
||||
|
||||
drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
|
||||
|
||||
return 0;
|
||||
|
@ -20,6 +20,7 @@ struct mtk_plane_pending_state {
|
||||
unsigned int y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int rotation;
|
||||
bool dirty;
|
||||
};
|
||||
|
||||
@ -35,6 +36,7 @@ to_mtk_plane_state(struct drm_plane_state *state)
|
||||
}
|
||||
|
||||
int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
unsigned long possible_crtcs, enum drm_plane_type type);
|
||||
unsigned long possible_crtcs, enum drm_plane_type type,
|
||||
unsigned int supported_rotations);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user