Commit c222f399 authored by Maxime Ripard's avatar Maxime Ripard

drm/sun4i: Fix formats usable by the primary plane

Even though all our planes can support the ARGB formats, the lowest plane
(ie the primary plane) cannot use the alpha component, otherwise it will
just result in the transparent area being entirely black.

Since some applications will still require the ARGB format, let's force the
format to XRGB to drop the alpha component entirely.
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
parent ac412c3d
...@@ -83,8 +83,13 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend, ...@@ -83,8 +83,13 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend,
} }
EXPORT_SYMBOL(sun4i_backend_layer_enable); EXPORT_SYMBOL(sun4i_backend_layer_enable);
static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
u32 format, u32 *mode)
{ {
if ((plane->type == DRM_PLANE_TYPE_PRIMARY) &&
(format == DRM_FORMAT_ARGB8888))
format = DRM_FORMAT_XRGB8888;
switch (format) { switch (format) {
case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ARGB8888:
*mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
...@@ -164,7 +169,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, ...@@ -164,7 +169,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n",
interlaced ? "on" : "off"); interlaced ? "on" : "off");
ret = sun4i_backend_drm_format_to_layer(fb->pixel_format, &val); ret = sun4i_backend_drm_format_to_layer(plane, fb->pixel_format, &val);
if (ret) { if (ret) {
DRM_DEBUG_DRIVER("Invalid format\n"); DRM_DEBUG_DRIVER("Invalid format\n");
return val; return val;
......
...@@ -19,7 +19,12 @@ ...@@ -19,7 +19,12 @@
#include "sun4i_drv.h" #include "sun4i_drv.h"
#include "sun4i_layer.h" #include "sun4i_layer.h"
#define SUN4I_NUM_LAYERS 2 struct sun4i_plane_desc {
enum drm_plane_type type;
u8 pipe;
const uint32_t *formats;
uint32_t nformats;
};
static int sun4i_backend_layer_atomic_check(struct drm_plane *plane, static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
...@@ -65,14 +70,35 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = { ...@@ -65,14 +70,35 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
.update_plane = drm_atomic_helper_update_plane, .update_plane = drm_atomic_helper_update_plane,
}; };
static const uint32_t sun4i_backend_layer_formats[] = { static const uint32_t sun4i_backend_layer_formats_primary[] = {
DRM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888,
DRM_FORMAT_RGB888,
DRM_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888,
};
static const uint32_t sun4i_backend_layer_formats_overlay[] = {
DRM_FORMAT_ARGB8888,
DRM_FORMAT_RGB888, DRM_FORMAT_RGB888,
DRM_FORMAT_XRGB8888,
};
static const struct sun4i_plane_desc sun4i_backend_planes[] = {
{
.type = DRM_PLANE_TYPE_PRIMARY,
.pipe = 0,
.formats = sun4i_backend_layer_formats_primary,
.nformats = ARRAY_SIZE(sun4i_backend_layer_formats_primary),
},
{
.type = DRM_PLANE_TYPE_OVERLAY,
.pipe = 1,
.formats = sun4i_backend_layer_formats_overlay,
.nformats = ARRAY_SIZE(sun4i_backend_layer_formats_overlay),
},
}; };
static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
enum drm_plane_type type) const struct sun4i_plane_desc *plane)
{ {
struct sun4i_drv *drv = drm->dev_private; struct sun4i_drv *drv = drm->dev_private;
struct sun4i_layer *layer; struct sun4i_layer *layer;
...@@ -84,10 +110,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, ...@@ -84,10 +110,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
ret = drm_universal_plane_init(drm, &layer->plane, BIT(0), ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
&sun4i_backend_layer_funcs, &sun4i_backend_layer_funcs,
sun4i_backend_layer_formats, plane->formats, plane->nformats,
ARRAY_SIZE(sun4i_backend_layer_formats), plane->type, NULL);
type,
NULL);
if (ret) { if (ret) {
dev_err(drm->dev, "Couldn't initialize layer\n"); dev_err(drm->dev, "Couldn't initialize layer\n");
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -97,7 +121,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, ...@@ -97,7 +121,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
&sun4i_backend_layer_helper_funcs); &sun4i_backend_layer_helper_funcs);
layer->drv = drv; layer->drv = drv;
if (type == DRM_PLANE_TYPE_PRIMARY) if (plane->type == DRM_PLANE_TYPE_PRIMARY)
drv->primary = &layer->plane; drv->primary = &layer->plane;
return layer; return layer;
...@@ -109,8 +133,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) ...@@ -109,8 +133,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
struct sun4i_layer **layers; struct sun4i_layer **layers;
int i; int i;
layers = devm_kcalloc(drm->dev, SUN4I_NUM_LAYERS, sizeof(**layers), layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes),
GFP_KERNEL); sizeof(**layers), GFP_KERNEL);
if (!layers) if (!layers)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -135,13 +159,11 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) ...@@ -135,13 +159,11 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
* SoCs that support it, sprites could fill the need for more * SoCs that support it, sprites could fill the need for more
* layers. * layers.
*/ */
for (i = 0; i < SUN4I_NUM_LAYERS; i++) { for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) {
enum drm_plane_type type = (i == 0) const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i];
? DRM_PLANE_TYPE_PRIMARY
: DRM_PLANE_TYPE_OVERLAY;
struct sun4i_layer *layer = layers[i]; struct sun4i_layer *layer = layers[i];
layer = sun4i_layer_init_one(drm, type); layer = sun4i_layer_init_one(drm, plane);
if (IS_ERR(layer)) { if (IS_ERR(layer)) {
dev_err(drm->dev, "Couldn't initialize %s plane\n", dev_err(drm->dev, "Couldn't initialize %s plane\n",
i ? "overlay" : "primary"); i ? "overlay" : "primary");
...@@ -149,10 +171,10 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) ...@@ -149,10 +171,10 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
}; };
DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
i ? "overlay" : "primary", i); i ? "overlay" : "primary", plane->pipe);
regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK,
SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(i)); SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe));
layer->id = i; layer->id = i;
}; };
......
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