aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c19
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.h3
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.c5
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.h9
-rw-r--r--drivers/gpu/drm/arm/malidp_planes.c96
5 files changed, 92 insertions, 40 deletions
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index d53b625b14fe..ebf90c794eab 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -42,6 +42,7 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm)
42 struct malidp_hw_device *hwdev = malidp->dev; 42 struct malidp_hw_device *hwdev = malidp->dev;
43 int ret; 43 int ret;
44 44
45 atomic_set(&malidp->config_valid, 0);
45 hwdev->set_config_valid(hwdev); 46 hwdev->set_config_valid(hwdev);
46 /* don't wait for config_valid flag if we are in config mode */ 47 /* don't wait for config_valid flag if we are in config mode */
47 if (hwdev->in_config_mode(hwdev)) 48 if (hwdev->in_config_mode(hwdev))
@@ -91,8 +92,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
91 92
92 drm_atomic_helper_commit_modeset_disables(drm, state); 93 drm_atomic_helper_commit_modeset_disables(drm, state);
93 drm_atomic_helper_commit_modeset_enables(drm, state); 94 drm_atomic_helper_commit_modeset_enables(drm, state);
94 drm_atomic_helper_commit_planes(drm, state, 95 drm_atomic_helper_commit_planes(drm, state, 0);
95 DRM_PLANE_COMMIT_ACTIVE_ONLY);
96 96
97 malidp_atomic_commit_hw_done(state); 97 malidp_atomic_commit_hw_done(state);
98 98
@@ -155,6 +155,12 @@ static int malidp_init(struct drm_device *drm)
155 return 0; 155 return 0;
156} 156}
157 157
158static void malidp_fini(struct drm_device *drm)
159{
160 malidp_de_planes_destroy(drm);
161 drm_mode_config_cleanup(drm);
162}
163
158static int malidp_irq_init(struct platform_device *pdev) 164static int malidp_irq_init(struct platform_device *pdev)
159{ 165{
160 int irq_de, irq_se, ret = 0; 166 int irq_de, irq_se, ret = 0;
@@ -375,6 +381,8 @@ static int malidp_bind(struct device *dev)
375 if (ret < 0) 381 if (ret < 0)
376 goto irq_init_fail; 382 goto irq_init_fail;
377 383
384 drm->irq_enabled = true;
385
378 ret = drm_vblank_init(drm, drm->mode_config.num_crtc); 386 ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
379 if (ret < 0) { 387 if (ret < 0) {
380 DRM_ERROR("failed to initialise vblank\n"); 388 DRM_ERROR("failed to initialise vblank\n");
@@ -400,6 +408,7 @@ fbdev_fail:
400vblank_fail: 408vblank_fail:
401 malidp_se_irq_fini(drm); 409 malidp_se_irq_fini(drm);
402 malidp_de_irq_fini(drm); 410 malidp_de_irq_fini(drm);
411 drm->irq_enabled = false;
403irq_init_fail: 412irq_init_fail:
404 component_unbind_all(dev, drm); 413 component_unbind_all(dev, drm);
405bind_fail: 414bind_fail:
@@ -408,8 +417,7 @@ bind_fail:
408port_fail: 417port_fail:
409 drm_dev_unregister(drm); 418 drm_dev_unregister(drm);
410register_fail: 419register_fail:
411 malidp_de_planes_destroy(drm); 420 malidp_fini(drm);
412 drm_mode_config_cleanup(drm);
413init_fail: 421init_fail:
414 drm->dev_private = NULL; 422 drm->dev_private = NULL;
415 dev_set_drvdata(dev, NULL); 423 dev_set_drvdata(dev, NULL);
@@ -442,8 +450,7 @@ static void malidp_unbind(struct device *dev)
442 of_node_put(malidp->crtc.port); 450 of_node_put(malidp->crtc.port);
443 malidp->crtc.port = NULL; 451 malidp->crtc.port = NULL;
444 drm_dev_unregister(drm); 452 drm_dev_unregister(drm);
445 malidp_de_planes_destroy(drm); 453 malidp_fini(drm);
446 drm_mode_config_cleanup(drm);
447 drm->dev_private = NULL; 454 drm->dev_private = NULL;
448 dev_set_drvdata(dev, NULL); 455 dev_set_drvdata(dev, NULL);
449 clk_disable_unprepare(hwdev->mclk); 456 clk_disable_unprepare(hwdev->mclk);
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index 271d2fb9711c..9fc8a2e405e4 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -39,6 +39,9 @@ struct malidp_plane_state {
39 39
40 /* size of the required rotation memory if plane is rotated */ 40 /* size of the required rotation memory if plane is rotated */
41 u32 rotmem_size; 41 u32 rotmem_size;
42 /* internal format ID */
43 u8 format;
44 u8 n_planes;
42}; 45};
43 46
44#define to_malidp_plane(x) container_of(x, struct malidp_plane, base) 47#define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index be815d0cc772..4bdf531f7844 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -125,6 +125,7 @@ static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
125{ 125{
126 u32 status, count = 100; 126 u32 status, count = 100;
127 127
128 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
128 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL); 129 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
129 while (count) { 130 while (count) {
130 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); 131 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
@@ -266,6 +267,7 @@ static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
266{ 267{
267 u32 status, count = 100; 268 u32 status, count = 100;
268 269
270 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
269 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL); 271 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
270 while (count) { 272 while (count) {
271 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); 273 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
@@ -436,6 +438,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
436 }, 438 },
437 .input_formats = malidp500_de_formats, 439 .input_formats = malidp500_de_formats,
438 .n_input_formats = ARRAY_SIZE(malidp500_de_formats), 440 .n_input_formats = ARRAY_SIZE(malidp500_de_formats),
441 .bus_align_bytes = 8,
439 }, 442 },
440 .query_hw = malidp500_query_hw, 443 .query_hw = malidp500_query_hw,
441 .enter_config_mode = malidp500_enter_config_mode, 444 .enter_config_mode = malidp500_enter_config_mode,
@@ -468,6 +471,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
468 }, 471 },
469 .input_formats = malidp550_de_formats, 472 .input_formats = malidp550_de_formats,
470 .n_input_formats = ARRAY_SIZE(malidp550_de_formats), 473 .n_input_formats = ARRAY_SIZE(malidp550_de_formats),
474 .bus_align_bytes = 8,
471 }, 475 },
472 .query_hw = malidp550_query_hw, 476 .query_hw = malidp550_query_hw,
473 .enter_config_mode = malidp550_enter_config_mode, 477 .enter_config_mode = malidp550_enter_config_mode,
@@ -501,6 +505,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
501 }, 505 },
502 .input_formats = malidp550_de_formats, 506 .input_formats = malidp550_de_formats,
503 .n_input_formats = ARRAY_SIZE(malidp550_de_formats), 507 .n_input_formats = ARRAY_SIZE(malidp550_de_formats),
508 .bus_align_bytes = 16,
504 }, 509 },
505 .query_hw = malidp650_query_hw, 510 .query_hw = malidp650_query_hw,
506 .enter_config_mode = malidp550_enter_config_mode, 511 .enter_config_mode = malidp550_enter_config_mode,
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index 141743e9f3a6..087e1202db3d 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -88,6 +88,9 @@ struct malidp_hw_regmap {
88 /* list of supported input formats for each layer */ 88 /* list of supported input formats for each layer */
89 const struct malidp_input_format *input_formats; 89 const struct malidp_input_format *input_formats;
90 const u8 n_input_formats; 90 const u8 n_input_formats;
91
92 /* pitch alignment requirement in bytes */
93 const u8 bus_align_bytes;
91}; 94};
92 95
93struct malidp_hw_device { 96struct malidp_hw_device {
@@ -229,6 +232,12 @@ void malidp_se_irq_fini(struct drm_device *drm);
229u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, 232u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
230 u8 layer_id, u32 format); 233 u8 layer_id, u32 format);
231 234
235static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev,
236 unsigned int pitch)
237{
238 return !(pitch & (hwdev->map.bus_align_bytes - 1));
239}
240
232/* 241/*
233 * background color components are defined as 12bits values, 242 * background color components are defined as 12bits values,
234 * they will be shifted right when stored on hardware that 243 * they will be shifted right when stored on hardware that
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index abaca03b9d36..63eec8f37cfc 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -27,6 +27,10 @@
27#define LAYER_H_FLIP (1 << 10) 27#define LAYER_H_FLIP (1 << 10)
28#define LAYER_V_FLIP (1 << 11) 28#define LAYER_V_FLIP (1 << 11)
29#define LAYER_ROT_MASK (0xf << 8) 29#define LAYER_ROT_MASK (0xf << 8)
30#define LAYER_COMP_MASK (0x3 << 12)
31#define LAYER_COMP_PIXEL (0x3 << 12)
32#define LAYER_COMP_PLANE (0x2 << 12)
33#define MALIDP_LAYER_COMPOSE 0x008
30#define MALIDP_LAYER_SIZE 0x00c 34#define MALIDP_LAYER_SIZE 0x00c
31#define LAYER_H_VAL(x) (((x) & 0x1fff) << 0) 35#define LAYER_H_VAL(x) (((x) & 0x1fff) << 0)
32#define LAYER_V_VAL(x) (((x) & 0x1fff) << 16) 36#define LAYER_V_VAL(x) (((x) & 0x1fff) << 16)
@@ -34,6 +38,14 @@
34#define MALIDP_LAYER_OFFSET 0x014 38#define MALIDP_LAYER_OFFSET 0x014
35#define MALIDP_LAYER_STRIDE 0x018 39#define MALIDP_LAYER_STRIDE 0x018
36 40
41/*
42 * This 4-entry look-up-table is used to determine the full 8-bit alpha value
43 * for formats with 1- or 2-bit alpha channels.
44 * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0%
45 * opacity for 2-bit formats.
46 */
47#define MALIDP_ALPHA_LUT 0xffaa5500
48
37static void malidp_de_plane_destroy(struct drm_plane *plane) 49static void malidp_de_plane_destroy(struct drm_plane *plane)
38{ 50{
39 struct malidp_plane *mp = to_malidp_plane(plane); 51 struct malidp_plane *mp = to_malidp_plane(plane);
@@ -46,7 +58,8 @@ static void malidp_de_plane_destroy(struct drm_plane *plane)
46 devm_kfree(plane->dev->dev, mp); 58 devm_kfree(plane->dev->dev, mp);
47} 59}
48 60
49struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) 61static struct
62drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
50{ 63{
51 struct malidp_plane_state *state, *m_state; 64 struct malidp_plane_state *state, *m_state;
52 65
@@ -58,13 +71,15 @@ struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
58 m_state = to_malidp_plane_state(plane->state); 71 m_state = to_malidp_plane_state(plane->state);
59 __drm_atomic_helper_plane_duplicate_state(plane, &state->base); 72 __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
60 state->rotmem_size = m_state->rotmem_size; 73 state->rotmem_size = m_state->rotmem_size;
74 state->format = m_state->format;
75 state->n_planes = m_state->n_planes;
61 } 76 }
62 77
63 return &state->base; 78 return &state->base;
64} 79}
65 80
66void malidp_destroy_plane_state(struct drm_plane *plane, 81static void malidp_destroy_plane_state(struct drm_plane *plane,
67 struct drm_plane_state *state) 82 struct drm_plane_state *state)
68{ 83{
69 struct malidp_plane_state *m_state = to_malidp_plane_state(state); 84 struct malidp_plane_state *m_state = to_malidp_plane_state(state);
70 85
@@ -75,6 +90,7 @@ void malidp_destroy_plane_state(struct drm_plane *plane,
75static const struct drm_plane_funcs malidp_de_plane_funcs = { 90static const struct drm_plane_funcs malidp_de_plane_funcs = {
76 .update_plane = drm_atomic_helper_update_plane, 91 .update_plane = drm_atomic_helper_update_plane,
77 .disable_plane = drm_atomic_helper_disable_plane, 92 .disable_plane = drm_atomic_helper_disable_plane,
93 .set_property = drm_atomic_helper_plane_set_property,
78 .destroy = malidp_de_plane_destroy, 94 .destroy = malidp_de_plane_destroy,
79 .reset = drm_atomic_helper_plane_reset, 95 .reset = drm_atomic_helper_plane_reset,
80 .atomic_duplicate_state = malidp_duplicate_plane_state, 96 .atomic_duplicate_state = malidp_duplicate_plane_state,
@@ -86,17 +102,29 @@ static int malidp_de_plane_check(struct drm_plane *plane,
86{ 102{
87 struct malidp_plane *mp = to_malidp_plane(plane); 103 struct malidp_plane *mp = to_malidp_plane(plane);
88 struct malidp_plane_state *ms = to_malidp_plane_state(state); 104 struct malidp_plane_state *ms = to_malidp_plane_state(state);
89 u8 format_id; 105 struct drm_framebuffer *fb;
106 int i;
90 u32 src_w, src_h; 107 u32 src_w, src_h;
91 108
92 if (!state->crtc || !state->fb) 109 if (!state->crtc || !state->fb)
93 return 0; 110 return 0;
94 111
95 format_id = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, 112 fb = state->fb;
96 state->fb->pixel_format); 113
97 if (format_id == MALIDP_INVALID_FORMAT_ID) 114 ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id,
115 fb->pixel_format);
116 if (ms->format == MALIDP_INVALID_FORMAT_ID)
98 return -EINVAL; 117 return -EINVAL;
99 118
119 ms->n_planes = drm_format_num_planes(fb->pixel_format);
120 for (i = 0; i < ms->n_planes; i++) {
121 if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) {
122 DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
123 fb->pitches[i], i);
124 return -EINVAL;
125 }
126 }
127
100 src_w = state->src_w >> 16; 128 src_w = state->src_w >> 16;
101 src_h = state->src_h >> 16; 129 src_h = state->src_h >> 16;
102 130
@@ -135,17 +163,13 @@ static void malidp_de_plane_update(struct drm_plane *plane,
135 struct drm_gem_cma_object *obj; 163 struct drm_gem_cma_object *obj;
136 struct malidp_plane *mp; 164 struct malidp_plane *mp;
137 const struct malidp_hw_regmap *map; 165 const struct malidp_hw_regmap *map;
138 u8 format_id; 166 struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
139 u16 ptr; 167 u16 ptr;
140 u32 format, src_w, src_h, dest_w, dest_h, val = 0; 168 u32 src_w, src_h, dest_w, dest_h, val;
141 int num_planes, i; 169 int i;
142 170
143 mp = to_malidp_plane(plane); 171 mp = to_malidp_plane(plane);
144
145 map = &mp->hwdev->map; 172 map = &mp->hwdev->map;
146 format = plane->state->fb->pixel_format;
147 format_id = malidp_hw_get_format_id(map, mp->layer->id, format);
148 num_planes = drm_format_num_planes(format);
149 173
150 /* convert src values from Q16 fixed point to integer */ 174 /* convert src values from Q16 fixed point to integer */
151 src_w = plane->state->src_w >> 16; 175 src_w = plane->state->src_w >> 16;
@@ -158,9 +182,9 @@ static void malidp_de_plane_update(struct drm_plane *plane,
158 dest_h = plane->state->crtc_h; 182 dest_h = plane->state->crtc_h;
159 } 183 }
160 184
161 malidp_hw_write(mp->hwdev, format_id, mp->layer->base); 185 malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
162 186
163 for (i = 0; i < num_planes; i++) { 187 for (i = 0; i < ms->n_planes; i++) {
164 /* calculate the offset for the layer's plane registers */ 188 /* calculate the offset for the layer's plane registers */
165 ptr = mp->layer->ptr + (i << 4); 189 ptr = mp->layer->ptr + (i << 4);
166 190
@@ -181,9 +205,9 @@ static void malidp_de_plane_update(struct drm_plane *plane,
181 LAYER_V_VAL(plane->state->crtc_y), 205 LAYER_V_VAL(plane->state->crtc_y),
182 mp->layer->base + MALIDP_LAYER_OFFSET); 206 mp->layer->base + MALIDP_LAYER_OFFSET);
183 207
184 /* first clear the rotation bits in the register */ 208 /* first clear the rotation bits */
185 malidp_hw_clearbits(mp->hwdev, LAYER_ROT_MASK, 209 val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
186 mp->layer->base + MALIDP_LAYER_CONTROL); 210 val &= ~LAYER_ROT_MASK;
187 211
188 /* setup the rotation and axis flip bits */ 212 /* setup the rotation and axis flip bits */
189 if (plane->state->rotation & DRM_ROTATE_MASK) 213 if (plane->state->rotation & DRM_ROTATE_MASK)
@@ -193,11 +217,18 @@ static void malidp_de_plane_update(struct drm_plane *plane,
193 if (plane->state->rotation & DRM_REFLECT_Y) 217 if (plane->state->rotation & DRM_REFLECT_Y)
194 val |= LAYER_H_FLIP; 218 val |= LAYER_H_FLIP;
195 219
220 /*
221 * always enable pixel alpha blending until we have a way to change
222 * blend modes
223 */
224 val &= ~LAYER_COMP_MASK;
225 val |= LAYER_COMP_PIXEL;
226
196 /* set the 'enable layer' bit */ 227 /* set the 'enable layer' bit */
197 val |= LAYER_ENABLE; 228 val |= LAYER_ENABLE;
198 229
199 malidp_hw_setbits(mp->hwdev, val, 230 malidp_hw_write(mp->hwdev, val,
200 mp->layer->base + MALIDP_LAYER_CONTROL); 231 mp->layer->base + MALIDP_LAYER_CONTROL);
201} 232}
202 233
203static void malidp_de_plane_disable(struct drm_plane *plane, 234static void malidp_de_plane_disable(struct drm_plane *plane,
@@ -222,6 +253,8 @@ int malidp_de_planes_init(struct drm_device *drm)
222 struct malidp_plane *plane = NULL; 253 struct malidp_plane *plane = NULL;
223 enum drm_plane_type plane_type; 254 enum drm_plane_type plane_type;
224 unsigned long crtcs = 1 << drm->mode_config.num_crtc; 255 unsigned long crtcs = 1 << drm->mode_config.num_crtc;
256 unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 |
257 DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y;
225 u32 *formats; 258 u32 *formats;
226 int ret, i, j, n; 259 int ret, i, j, n;
227 260
@@ -254,23 +287,18 @@ int malidp_de_planes_init(struct drm_device *drm)
254 if (ret < 0) 287 if (ret < 0)
255 goto cleanup; 288 goto cleanup;
256 289
257 /* SMART layer can't be rotated */
258 if (id != DE_SMART) {
259 unsigned long flags = DRM_ROTATE_0 |
260 DRM_ROTATE_90 |
261 DRM_ROTATE_180 |
262 DRM_ROTATE_270 |
263 DRM_REFLECT_X |
264 DRM_REFLECT_Y;
265 drm_plane_create_rotation_property(&plane->base,
266 DRM_ROTATE_0,
267 flags);
268 }
269
270 drm_plane_helper_add(&plane->base, 290 drm_plane_helper_add(&plane->base,
271 &malidp_de_plane_helper_funcs); 291 &malidp_de_plane_helper_funcs);
272 plane->hwdev = malidp->dev; 292 plane->hwdev = malidp->dev;
273 plane->layer = &map->layers[i]; 293 plane->layer = &map->layers[i];
294
295 /* Skip the features which the SMART layer doesn't have */
296 if (id == DE_SMART)
297 continue;
298
299 drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags);
300 malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
301 plane->layer->base + MALIDP_LAYER_COMPOSE);
274 } 302 }
275 303
276 kfree(formats); 304 kfree(formats);