aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2016-09-19 16:17:50 -0400
committerMaxime Ripard <maxime.ripard@free-electrons.com>2016-09-22 03:10:54 -0400
commitc222f399045de480d4af0b9e4cdfff1a083e3e1d (patch)
tree3b1a7c9917deb1709da43d64113e0b776e0111a2
parentac412c3d4ff216cb7315cd695be0956ca948aae6 (diff)
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: Maxime Ripard <maxime.ripard@free-electrons.com>
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c9
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.c56
2 files changed, 46 insertions, 19 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index fcd4e912c0d7..32c0584e3c35 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -83,8 +83,13 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend,
83} 83}
84EXPORT_SYMBOL(sun4i_backend_layer_enable); 84EXPORT_SYMBOL(sun4i_backend_layer_enable);
85 85
86static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) 86static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
87 u32 format, u32 *mode)
87{ 88{
89 if ((plane->type == DRM_PLANE_TYPE_PRIMARY) &&
90 (format == DRM_FORMAT_ARGB8888))
91 format = DRM_FORMAT_XRGB8888;
92
88 switch (format) { 93 switch (format) {
89 case DRM_FORMAT_ARGB8888: 94 case DRM_FORMAT_ARGB8888:
90 *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; 95 *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
@@ -164,7 +169,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
164 DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", 169 DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n",
165 interlaced ? "on" : "off"); 170 interlaced ? "on" : "off");
166 171
167 ret = sun4i_backend_drm_format_to_layer(fb->pixel_format, &val); 172 ret = sun4i_backend_drm_format_to_layer(plane, fb->pixel_format, &val);
168 if (ret) { 173 if (ret) {
169 DRM_DEBUG_DRIVER("Invalid format\n"); 174 DRM_DEBUG_DRIVER("Invalid format\n");
170 return val; 175 return val;
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 068ab806309b..f0035bf5efea 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -19,7 +19,12 @@
19#include "sun4i_drv.h" 19#include "sun4i_drv.h"
20#include "sun4i_layer.h" 20#include "sun4i_layer.h"
21 21
22#define SUN4I_NUM_LAYERS 2 22struct sun4i_plane_desc {
23 enum drm_plane_type type;
24 u8 pipe;
25 const uint32_t *formats;
26 uint32_t nformats;
27};
23 28
24static int sun4i_backend_layer_atomic_check(struct drm_plane *plane, 29static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
25 struct drm_plane_state *state) 30 struct drm_plane_state *state)
@@ -65,14 +70,35 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
65 .update_plane = drm_atomic_helper_update_plane, 70 .update_plane = drm_atomic_helper_update_plane,
66}; 71};
67 72
68static const uint32_t sun4i_backend_layer_formats[] = { 73static const uint32_t sun4i_backend_layer_formats_primary[] = {
69 DRM_FORMAT_ARGB8888, 74 DRM_FORMAT_ARGB8888,
75 DRM_FORMAT_RGB888,
70 DRM_FORMAT_XRGB8888, 76 DRM_FORMAT_XRGB8888,
77};
78
79static const uint32_t sun4i_backend_layer_formats_overlay[] = {
80 DRM_FORMAT_ARGB8888,
71 DRM_FORMAT_RGB888, 81 DRM_FORMAT_RGB888,
82 DRM_FORMAT_XRGB8888,
83};
84
85static const struct sun4i_plane_desc sun4i_backend_planes[] = {
86 {
87 .type = DRM_PLANE_TYPE_PRIMARY,
88 .pipe = 0,
89 .formats = sun4i_backend_layer_formats_primary,
90 .nformats = ARRAY_SIZE(sun4i_backend_layer_formats_primary),
91 },
92 {
93 .type = DRM_PLANE_TYPE_OVERLAY,
94 .pipe = 1,
95 .formats = sun4i_backend_layer_formats_overlay,
96 .nformats = ARRAY_SIZE(sun4i_backend_layer_formats_overlay),
97 },
72}; 98};
73 99
74static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, 100static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
75 enum drm_plane_type type) 101 const struct sun4i_plane_desc *plane)
76{ 102{
77 struct sun4i_drv *drv = drm->dev_private; 103 struct sun4i_drv *drv = drm->dev_private;
78 struct sun4i_layer *layer; 104 struct sun4i_layer *layer;
@@ -84,10 +110,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
84 110
85 ret = drm_universal_plane_init(drm, &layer->plane, BIT(0), 111 ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
86 &sun4i_backend_layer_funcs, 112 &sun4i_backend_layer_funcs,
87 sun4i_backend_layer_formats, 113 plane->formats, plane->nformats,
88 ARRAY_SIZE(sun4i_backend_layer_formats), 114 plane->type, NULL);
89 type,
90 NULL);
91 if (ret) { 115 if (ret) {
92 dev_err(drm->dev, "Couldn't initialize layer\n"); 116 dev_err(drm->dev, "Couldn't initialize layer\n");
93 return ERR_PTR(ret); 117 return ERR_PTR(ret);
@@ -97,7 +121,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
97 &sun4i_backend_layer_helper_funcs); 121 &sun4i_backend_layer_helper_funcs);
98 layer->drv = drv; 122 layer->drv = drv;
99 123
100 if (type == DRM_PLANE_TYPE_PRIMARY) 124 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
101 drv->primary = &layer->plane; 125 drv->primary = &layer->plane;
102 126
103 return layer; 127 return layer;
@@ -109,8 +133,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
109 struct sun4i_layer **layers; 133 struct sun4i_layer **layers;
110 int i; 134 int i;
111 135
112 layers = devm_kcalloc(drm->dev, SUN4I_NUM_LAYERS, sizeof(**layers), 136 layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes),
113 GFP_KERNEL); 137 sizeof(**layers), GFP_KERNEL);
114 if (!layers) 138 if (!layers)
115 return ERR_PTR(-ENOMEM); 139 return ERR_PTR(-ENOMEM);
116 140
@@ -135,13 +159,11 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
135 * SoCs that support it, sprites could fill the need for more 159 * SoCs that support it, sprites could fill the need for more
136 * layers. 160 * layers.
137 */ 161 */
138 for (i = 0; i < SUN4I_NUM_LAYERS; i++) { 162 for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) {
139 enum drm_plane_type type = (i == 0) 163 const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i];
140 ? DRM_PLANE_TYPE_PRIMARY
141 : DRM_PLANE_TYPE_OVERLAY;
142 struct sun4i_layer *layer = layers[i]; 164 struct sun4i_layer *layer = layers[i];
143 165
144 layer = sun4i_layer_init_one(drm, type); 166 layer = sun4i_layer_init_one(drm, plane);
145 if (IS_ERR(layer)) { 167 if (IS_ERR(layer)) {
146 dev_err(drm->dev, "Couldn't initialize %s plane\n", 168 dev_err(drm->dev, "Couldn't initialize %s plane\n",
147 i ? "overlay" : "primary"); 169 i ? "overlay" : "primary");
@@ -149,10 +171,10 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
149 }; 171 };
150 172
151 DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", 173 DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
152 i ? "overlay" : "primary", i); 174 i ? "overlay" : "primary", plane->pipe);
153 regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), 175 regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
154 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, 176 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK,
155 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(i)); 177 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe));
156 178
157 layer->id = i; 179 layer->id = i;
158 }; 180 };