Commit 9d75b8c0 authored by Icenowy Zheng's avatar Icenowy Zheng Committed by Maxime Ripard

drm/sun4i: add support for Allwinner DE2 mixers

Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
with mixers to do graphic processing and feed data to TCON, like the old
backends and frontends.

Add support for the mixer on Allwinner V3s SoC; it's the simplest one.

Currently a lot of functions are still missing -- more investigations
are needed to gain enough information for them.
Signed-off-by: default avatarIcenowy Zheng <icenowy@aosc.io>
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
parent a43a42ad
...@@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND ...@@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
original Allwinner Display Engine, which has a backend to original Allwinner Display Engine, which has a backend to
do some alpha blending and feed graphics to TCON. If M is do some alpha blending and feed graphics to TCON. If M is
selected the module will be called sun4i-backend. selected the module will be called sun4i-backend.
config DRM_SUN8I_MIXER
tristate "Support for Allwinner Display Engine 2.0 Mixer"
depends on DRM_SUN4I
default MACH_SUN8I
help
Choose this option if you have an Allwinner SoC with the
Allwinner Display Engine 2.0, which has a mixer to do some
graphics mixture and feed graphics to TCON, If M is
selected the module will be called sun8i-mixer.
...@@ -8,8 +8,11 @@ sun4i-tcon-y += sun4i_crtc.o ...@@ -8,8 +8,11 @@ sun4i-tcon-y += sun4i_crtc.o
sun4i-backend-y += sun4i_backend.o sun4i_layer.o sun4i-backend-y += sun4i_backend.o sun4i_layer.o
sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o
obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o
obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o
obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o
obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
/*
* Copyright (C) Icenowy Zheng <icenowy@aosc.io>
*
* Based on sun4i_layer.h, which is:
* Copyright (C) 2015 Free Electrons
* Copyright (C) 2015 NextThing Co
*
* Maxime Ripard <maxime.ripard@free-electrons.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drmP.h>
#include "sun8i_layer.h"
#include "sun8i_mixer.h"
struct sun8i_plane_desc {
enum drm_plane_type type;
const uint32_t *formats;
uint32_t nformats;
};
static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
struct sun8i_mixer *mixer = layer->mixer;
sun8i_mixer_layer_enable(mixer, layer->id, false);
}
static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
struct sun8i_mixer *mixer = layer->mixer;
sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
sun8i_mixer_layer_enable(mixer, layer->id, true);
}
static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
.atomic_disable = sun8i_mixer_layer_atomic_disable,
.atomic_update = sun8i_mixer_layer_atomic_update,
};
static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.destroy = drm_plane_cleanup,
.disable_plane = drm_atomic_helper_disable_plane,
.reset = drm_atomic_helper_plane_reset,
.update_plane = drm_atomic_helper_update_plane,
};
static const uint32_t sun8i_mixer_layer_formats[] = {
DRM_FORMAT_RGB888,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB8888,
};
static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
{
.type = DRM_PLANE_TYPE_PRIMARY,
.formats = sun8i_mixer_layer_formats,
.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
},
};
static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
struct sun8i_mixer *mixer,
const struct sun8i_plane_desc *plane)
{
struct sun8i_layer *layer;
int ret;
layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
if (!layer)
return ERR_PTR(-ENOMEM);
/* possible crtcs are set later */
ret = drm_universal_plane_init(drm, &layer->plane, 0,
&sun8i_mixer_layer_funcs,
plane->formats, plane->nformats,
plane->type, NULL);
if (ret) {
dev_err(drm->dev, "Couldn't initialize layer\n");
return ERR_PTR(ret);
}
drm_plane_helper_add(&layer->plane,
&sun8i_mixer_layer_helper_funcs);
layer->mixer = mixer;
return layer;
}
struct drm_plane **sun8i_layers_init(struct drm_device *drm,
struct sunxi_engine *engine)
{
struct drm_plane **planes;
struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
int i;
planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
sizeof(*planes), GFP_KERNEL);
if (!planes)
return ERR_PTR(-ENOMEM);
for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
struct sun8i_layer *layer;
layer = sun8i_layer_init_one(drm, mixer, plane);
if (IS_ERR(layer)) {
dev_err(drm->dev, "Couldn't initialize %s plane\n",
i ? "overlay" : "primary");
return ERR_CAST(layer);
};
layer->id = i;
planes[i] = &layer->plane;
};
return planes;
}
/*
* Copyright (C) Icenowy Zheng <icenowy@aosc.io>
*
* Based on sun4i_layer.h, which is:
* Copyright (C) 2015 Free Electrons
* Copyright (C) 2015 NextThing Co
*
* Maxime Ripard <maxime.ripard@free-electrons.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
#ifndef _SUN8I_LAYER_H_
#define _SUN8I_LAYER_H_
struct sunxi_engine;
struct sun8i_layer {
struct drm_plane plane;
struct sun4i_drv *drv;
struct sun8i_mixer *mixer;
int id;
};
static inline struct sun8i_layer *
plane_to_sun8i_layer(struct drm_plane *plane)
{
return container_of(plane, struct sun8i_layer, plane);
}
struct drm_plane **sun8i_layers_init(struct drm_device *drm,
struct sunxi_engine *engine);
#endif /* _SUN8I_LAYER_H_ */
This diff is collapsed.
/*
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
#ifndef _SUN8I_MIXER_H_
#define _SUN8I_MIXER_H_
#include <linux/clk.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include "sunxi_engine.h"
#define SUN8I_MIXER_MAX_CHAN_COUNT 4
#define SUN8I_MIXER_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1))
#define SUN8I_MIXER_COORD(x, y) ((y) << 16 | (x))
#define SUN8I_MIXER_GLOBAL_CTL 0x0
#define SUN8I_MIXER_GLOBAL_STATUS 0x4
#define SUN8I_MIXER_GLOBAL_DBUFF 0x8
#define SUN8I_MIXER_GLOBAL_SIZE 0xc
#define SUN8I_MIXER_GLOBAL_CTL_RT_EN 0x1
#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE 0x1
#define SUN8I_MIXER_BLEND_FCOLOR_CTL 0x1000
#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x) (0x1004 + 0x10 * (x) + 0x0)
#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x) (0x1004 + 0x10 * (x) + 0x4)
#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x) (0x1004 + 0x10 * (x) + 0x8)
#define SUN8I_MIXER_BLEND_ROUTE 0x1080
#define SUN8I_MIXER_BLEND_PREMULTIPLY 0x1084
#define SUN8I_MIXER_BLEND_BKCOLOR 0x1088
#define SUN8I_MIXER_BLEND_OUTSIZE 0x108c
#define SUN8I_MIXER_BLEND_MODE(x) (0x1090 + 0x04 * (x))
#define SUN8I_MIXER_BLEND_CK_CTL 0x10b0
#define SUN8I_MIXER_BLEND_CK_CFG 0x10b4
#define SUN8I_MIXER_BLEND_CK_MAX(x) (0x10c0 + 0x04 * (x))
#define SUN8I_MIXER_BLEND_CK_MIN(x) (0x10e0 + 0x04 * (x))
#define SUN8I_MIXER_BLEND_OUTCTL 0x10fc
/* The following numbers are some still unknown magic numbers */
#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF 0xff000000
#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF 0x00000101
#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF 0x0
#define SUN8I_MIXER_BLEND_BKCOLOR_DEF 0xff000000
#define SUN8I_MIXER_BLEND_MODE_DEF 0x03010301
#define SUN8I_MIXER_BLEND_CK_CTL_DEF 0x0
#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED BIT(1)
/*
* VI channels are not used now, but the support of them may be introduced in
* the future.
*/
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch) (0x2000 + 0x1000 * (ch) + 0x80)
#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch) (0x2000 + 0x1000 * (ch) + 0x84)
#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch) (0x2000 + 0x1000 * (ch) + 0x88)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN BIT(0)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK GENMASK(2, 1)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK GENMASK(11, 8)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK GENMASK(31, 24)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF (1 << 1)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888 (0 << 8)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888 (4 << 8)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888 (8 << 8)
#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF (0xff << 24)
/*
* These sub-engines are still unknown now, the EN registers are here only to
* be used to disable these sub-engines.
*/
#define SUN8I_MIXER_VSU_EN 0x20000
#define SUN8I_MIXER_GSU1_EN 0x30000
#define SUN8I_MIXER_GSU2_EN 0x40000
#define SUN8I_MIXER_GSU3_EN 0x50000
#define SUN8I_MIXER_FCE_EN 0xa0000
#define SUN8I_MIXER_BWS_EN 0xa2000
#define SUN8I_MIXER_LTI_EN 0xa4000
#define SUN8I_MIXER_PEAK_EN 0xa6000
#define SUN8I_MIXER_ASE_EN 0xa8000
#define SUN8I_MIXER_FCC_EN 0xaa000
#define SUN8I_MIXER_DCSC_EN 0xb0000
struct sun8i_mixer_cfg {
int vi_num;
int ui_num;
};
struct sun8i_mixer {
struct sunxi_engine engine;
const struct sun8i_mixer_cfg *cfg;
struct reset_control *reset;
struct clk *bus_clk;
struct clk *mod_clk;
};
static inline struct sun8i_mixer *
engine_to_sun8i_mixer(struct sunxi_engine *engine)
{
return container_of(engine, struct sun8i_mixer, engine);
}
void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
int layer, bool enable);
int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
int layer, struct drm_plane *plane);
int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
int layer, struct drm_plane *plane);
int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
int layer, struct drm_plane *plane);
#endif /* _SUN8I_MIXER_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