aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2015-02-05 10:32:33 -0500
committerBoris Brezillon <boris.brezillon@free-electrons.com>2015-02-22 15:00:06 -0500
commit2389fc1305fc1e2cf8b310a75463fefd3058bf48 (patch)
tree2f85d867f87406bbb0256cdffb3f85478e133326 /drivers/gpu/drm
parent45ee2dbc65cbf6910892c480e6f428be342fa733 (diff)
drm: atmel-hlcdc: Atomic mode-setting conversion
Convert the HLCDC driver to atomic mode-setting. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Tested-by: Sylvain Rochet <sylvain.rochet@finsecur.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c291
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c4
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h59
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c4
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.h3
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c41
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c549
7 files changed, 455 insertions, 496 deletions
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index 0409b907de5d..b0c06272a1cb 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -37,14 +37,14 @@
37 * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device 37 * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
38 * @event: pointer to the current page flip event 38 * @event: pointer to the current page flip event
39 * @id: CRTC id (returned by drm_crtc_index) 39 * @id: CRTC id (returned by drm_crtc_index)
40 * @dpms: DPMS mode 40 * @enabled: CRTC state
41 */ 41 */
42struct atmel_hlcdc_crtc { 42struct atmel_hlcdc_crtc {
43 struct drm_crtc base; 43 struct drm_crtc base;
44 struct atmel_hlcdc_dc *dc; 44 struct atmel_hlcdc_dc *dc;
45 struct drm_pending_vblank_event *event; 45 struct drm_pending_vblank_event *event;
46 int id; 46 int id;
47 int dpms; 47 bool enabled;
48}; 48};
49 49
50static inline struct atmel_hlcdc_crtc * 50static inline struct atmel_hlcdc_crtc *
@@ -53,86 +53,17 @@ drm_crtc_to_atmel_hlcdc_crtc(struct drm_crtc *crtc)
53 return container_of(crtc, struct atmel_hlcdc_crtc, base); 53 return container_of(crtc, struct atmel_hlcdc_crtc, base);
54} 54}
55 55
56static void atmel_hlcdc_crtc_dpms(struct drm_crtc *c, int mode) 56static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
57{ 57{
58 struct drm_device *dev = c->dev;
59 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 58 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
60 struct regmap *regmap = crtc->dc->hlcdc->regmap; 59 struct regmap *regmap = crtc->dc->hlcdc->regmap;
61 unsigned int status; 60 struct drm_display_mode *adj = &c->state->adjusted_mode;
62
63 if (mode != DRM_MODE_DPMS_ON)
64 mode = DRM_MODE_DPMS_OFF;
65
66 if (crtc->dpms == mode)
67 return;
68
69 pm_runtime_get_sync(dev->dev);
70
71 if (mode != DRM_MODE_DPMS_ON) {
72 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP);
73 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
74 (status & ATMEL_HLCDC_DISP))
75 cpu_relax();
76
77 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC);
78 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
79 (status & ATMEL_HLCDC_SYNC))
80 cpu_relax();
81
82 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK);
83 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
84 (status & ATMEL_HLCDC_PIXEL_CLK))
85 cpu_relax();
86
87 clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
88
89 pm_runtime_allow(dev->dev);
90 } else {
91 pm_runtime_forbid(dev->dev);
92
93 clk_prepare_enable(crtc->dc->hlcdc->sys_clk);
94
95 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK);
96 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
97 !(status & ATMEL_HLCDC_PIXEL_CLK))
98 cpu_relax();
99
100
101 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC);
102 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
103 !(status & ATMEL_HLCDC_SYNC))
104 cpu_relax();
105
106 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP);
107 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
108 !(status & ATMEL_HLCDC_DISP))
109 cpu_relax();
110 }
111
112 pm_runtime_put_sync(dev->dev);
113
114 crtc->dpms = mode;
115}
116
117static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c,
118 struct drm_display_mode *mode,
119 struct drm_display_mode *adj,
120 int x, int y,
121 struct drm_framebuffer *old_fb)
122{
123 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
124 struct regmap *regmap = crtc->dc->hlcdc->regmap;
125 struct drm_plane *plane = c->primary;
126 struct drm_framebuffer *fb;
127 unsigned long mode_rate; 61 unsigned long mode_rate;
128 struct videomode vm; 62 struct videomode vm;
129 unsigned long prate; 63 unsigned long prate;
130 unsigned int cfg; 64 unsigned int cfg;
131 int div; 65 int div;
132 66
133 if (atmel_hlcdc_dc_mode_valid(crtc->dc, adj) != MODE_OK)
134 return -EINVAL;
135
136 vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay; 67 vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay;
137 vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end; 68 vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end;
138 vm.vsync_len = adj->crtc_vsync_end - adj->crtc_vsync_start; 69 vm.vsync_len = adj->crtc_vsync_end - adj->crtc_vsync_start;
@@ -156,7 +87,7 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c,
156 cfg = ATMEL_HLCDC_CLKPOL; 87 cfg = ATMEL_HLCDC_CLKPOL;
157 88
158 prate = clk_get_rate(crtc->dc->hlcdc->sys_clk); 89 prate = clk_get_rate(crtc->dc->hlcdc->sys_clk);
159 mode_rate = mode->crtc_clock * 1000; 90 mode_rate = adj->crtc_clock * 1000;
160 if ((prate / 2) < mode_rate) { 91 if ((prate / 2) < mode_rate) {
161 prate *= 2; 92 prate *= 2;
162 cfg |= ATMEL_HLCDC_CLKSEL; 93 cfg |= ATMEL_HLCDC_CLKSEL;
@@ -174,10 +105,10 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c,
174 105
175 cfg = 0; 106 cfg = 0;
176 107
177 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 108 if (adj->flags & DRM_MODE_FLAG_NVSYNC)
178 cfg |= ATMEL_HLCDC_VSPOL; 109 cfg |= ATMEL_HLCDC_VSPOL;
179 110
180 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 111 if (adj->flags & DRM_MODE_FLAG_NHSYNC)
181 cfg |= ATMEL_HLCDC_HSPOL; 112 cfg |= ATMEL_HLCDC_HSPOL;
182 113
183 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), 114 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5),
@@ -187,77 +118,132 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c,
187 ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | 118 ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO |
188 ATMEL_HLCDC_GUARDTIME_MASK, 119 ATMEL_HLCDC_GUARDTIME_MASK,
189 cfg); 120 cfg);
190
191 fb = plane->fb;
192 plane->fb = old_fb;
193
194 return atmel_hlcdc_plane_update_with_mode(plane, c, fb, 0, 0,
195 adj->hdisplay, adj->vdisplay,
196 x << 16, y << 16,
197 adj->hdisplay << 16,
198 adj->vdisplay << 16,
199 adj);
200} 121}
201 122
202int atmel_hlcdc_crtc_mode_set_base(struct drm_crtc *c, int x, int y, 123static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *crtc,
203 struct drm_framebuffer *old_fb) 124 const struct drm_display_mode *mode,
125 struct drm_display_mode *adjusted_mode)
204{ 126{
205 struct drm_plane *plane = c->primary; 127 return true;
206 struct drm_framebuffer *fb = plane->fb;
207 struct drm_display_mode *mode = &c->hwmode;
208
209 plane->fb = old_fb;
210
211 return plane->funcs->update_plane(plane, c, fb,
212 0, 0,
213 mode->hdisplay,
214 mode->vdisplay,
215 x << 16, y << 16,
216 mode->hdisplay << 16,
217 mode->vdisplay << 16);
218} 128}
219 129
220static void atmel_hlcdc_crtc_prepare(struct drm_crtc *crtc) 130static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
221{ 131{
222 atmel_hlcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 132 struct drm_device *dev = c->dev;
133 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
134 struct regmap *regmap = crtc->dc->hlcdc->regmap;
135 unsigned int status;
136
137 if (!crtc->enabled)
138 return;
139
140 drm_crtc_vblank_off(c);
141
142 pm_runtime_get_sync(dev->dev);
143
144 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP);
145 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
146 (status & ATMEL_HLCDC_DISP))
147 cpu_relax();
148
149 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC);
150 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
151 (status & ATMEL_HLCDC_SYNC))
152 cpu_relax();
153
154 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK);
155 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
156 (status & ATMEL_HLCDC_PIXEL_CLK))
157 cpu_relax();
158
159 clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
160
161 pm_runtime_allow(dev->dev);
162
163 pm_runtime_put_sync(dev->dev);
164
165 crtc->enabled = false;
223} 166}
224 167
225static void atmel_hlcdc_crtc_commit(struct drm_crtc *crtc) 168static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
226{ 169{
227 atmel_hlcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 170 struct drm_device *dev = c->dev;
171 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
172 struct regmap *regmap = crtc->dc->hlcdc->regmap;
173 unsigned int status;
174
175 if (crtc->enabled)
176 return;
177
178 pm_runtime_get_sync(dev->dev);
179
180 pm_runtime_forbid(dev->dev);
181
182 clk_prepare_enable(crtc->dc->hlcdc->sys_clk);
183
184 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK);
185 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
186 !(status & ATMEL_HLCDC_PIXEL_CLK))
187 cpu_relax();
188
189
190 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC);
191 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
192 !(status & ATMEL_HLCDC_SYNC))
193 cpu_relax();
194
195 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP);
196 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
197 !(status & ATMEL_HLCDC_DISP))
198 cpu_relax();
199
200 pm_runtime_put_sync(dev->dev);
201
202 drm_crtc_vblank_on(c);
203
204 crtc->enabled = true;
228} 205}
229 206
230static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *crtc, 207static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
231 const struct drm_display_mode *mode, 208 struct drm_crtc_state *s)
232 struct drm_display_mode *adjusted_mode)
233{ 209{
234 return true; 210 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
211
212 if (atmel_hlcdc_dc_mode_valid(crtc->dc, &s->adjusted_mode) != MODE_OK)
213 return -EINVAL;
214
215 return 0;
235} 216}
236 217
237static void atmel_hlcdc_crtc_disable(struct drm_crtc *crtc) 218static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c)
238{ 219{
239 struct drm_plane *plane; 220 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
240 221
241 atmel_hlcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 222 if (c->state->event) {
242 crtc->primary->funcs->disable_plane(crtc->primary); 223 c->state->event->pipe = drm_crtc_index(c);
243 224
244 drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) { 225 WARN_ON(drm_crtc_vblank_get(c) != 0);
245 if (plane->crtc != crtc)
246 continue;
247 226
248 plane->funcs->disable_plane(crtc->primary); 227 crtc->event = c->state->event;
249 plane->crtc = NULL; 228 c->state->event = NULL;
250 } 229 }
251} 230}
252 231
232static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc)
233{
234 /* TODO: write common plane control register if available */
235}
236
253static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { 237static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = {
254 .mode_fixup = atmel_hlcdc_crtc_mode_fixup, 238 .mode_fixup = atmel_hlcdc_crtc_mode_fixup,
255 .dpms = atmel_hlcdc_crtc_dpms, 239 .mode_set = drm_helper_crtc_mode_set,
256 .mode_set = atmel_hlcdc_crtc_mode_set, 240 .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb,
257 .mode_set_base = atmel_hlcdc_crtc_mode_set_base, 241 .mode_set_base = drm_helper_crtc_mode_set_base,
258 .prepare = atmel_hlcdc_crtc_prepare,
259 .commit = atmel_hlcdc_crtc_commit,
260 .disable = atmel_hlcdc_crtc_disable, 242 .disable = atmel_hlcdc_crtc_disable,
243 .enable = atmel_hlcdc_crtc_enable,
244 .atomic_check = atmel_hlcdc_crtc_atomic_check,
245 .atomic_begin = atmel_hlcdc_crtc_atomic_begin,
246 .atomic_flush = atmel_hlcdc_crtc_atomic_flush,
261}; 247};
262 248
263static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c) 249static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c)
@@ -306,61 +292,13 @@ void atmel_hlcdc_crtc_irq(struct drm_crtc *c)
306 atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c)); 292 atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c));
307} 293}
308 294
309static int atmel_hlcdc_crtc_page_flip(struct drm_crtc *c,
310 struct drm_framebuffer *fb,
311 struct drm_pending_vblank_event *event,
312 uint32_t page_flip_flags)
313{
314 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
315 struct atmel_hlcdc_plane_update_req req;
316 struct drm_plane *plane = c->primary;
317 struct drm_device *dev = c->dev;
318 unsigned long flags;
319 int ret = 0;
320
321 spin_lock_irqsave(&dev->event_lock, flags);
322 if (crtc->event)
323 ret = -EBUSY;
324 spin_unlock_irqrestore(&dev->event_lock, flags);
325
326 if (ret)
327 return ret;
328
329 memset(&req, 0, sizeof(req));
330 req.crtc_x = 0;
331 req.crtc_y = 0;
332 req.crtc_h = c->mode.crtc_vdisplay;
333 req.crtc_w = c->mode.crtc_hdisplay;
334 req.src_x = c->x << 16;
335 req.src_y = c->y << 16;
336 req.src_w = req.crtc_w << 16;
337 req.src_h = req.crtc_h << 16;
338 req.fb = fb;
339
340 ret = atmel_hlcdc_plane_prepare_update_req(plane, &req, &c->hwmode);
341 if (ret)
342 return ret;
343
344 if (event) {
345 drm_vblank_get(c->dev, crtc->id);
346 spin_lock_irqsave(&dev->event_lock, flags);
347 crtc->event = event;
348 spin_unlock_irqrestore(&dev->event_lock, flags);
349 }
350
351 ret = atmel_hlcdc_plane_apply_update_req(plane, &req);
352 if (ret)
353 crtc->event = NULL;
354 else
355 plane->fb = fb;
356
357 return ret;
358}
359
360static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { 295static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
361 .page_flip = atmel_hlcdc_crtc_page_flip, 296 .page_flip = drm_atomic_helper_page_flip,
362 .set_config = drm_crtc_helper_set_config, 297 .set_config = drm_atomic_helper_set_config,
363 .destroy = atmel_hlcdc_crtc_destroy, 298 .destroy = atmel_hlcdc_crtc_destroy,
299 .reset = drm_atomic_helper_crtc_reset,
300 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
301 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
364}; 302};
365 303
366int atmel_hlcdc_crtc_create(struct drm_device *dev) 304int atmel_hlcdc_crtc_create(struct drm_device *dev)
@@ -375,7 +313,6 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
375 if (!crtc) 313 if (!crtc)
376 return -ENOMEM; 314 return -ENOMEM;
377 315
378 crtc->dpms = DRM_MODE_DPMS_OFF;
379 crtc->dc = dc; 316 crtc->dc = dc;
380 317
381 ret = drm_crtc_init_with_planes(dev, &crtc->base, 318 ret = drm_crtc_init_with_planes(dev, &crtc->base,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 7320a6c6613f..47fd1470f755 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -222,6 +222,8 @@ static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev)
222static const struct drm_mode_config_funcs mode_config_funcs = { 222static const struct drm_mode_config_funcs mode_config_funcs = {
223 .fb_create = atmel_hlcdc_fb_create, 223 .fb_create = atmel_hlcdc_fb_create,
224 .output_poll_changed = atmel_hlcdc_fb_output_poll_changed, 224 .output_poll_changed = atmel_hlcdc_fb_output_poll_changed,
225 .atomic_check = drm_atomic_helper_check,
226 .atomic_commit = drm_atomic_helper_commit,
225}; 227};
226 228
227static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev) 229static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
@@ -319,6 +321,8 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
319 goto err_periph_clk_disable; 321 goto err_periph_clk_disable;
320 } 322 }
321 323
324 drm_mode_config_reset(dev);
325
322 ret = drm_vblank_init(dev, 1); 326 ret = drm_vblank_init(dev, 1);
323 if (ret < 0) { 327 if (ret < 0) {
324 dev_err(dev->dev, "failed to initialize vblank\n"); 328 dev_err(dev->dev, "failed to initialize vblank\n");
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index 7bc96af3397a..015c3f13b7f8 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -26,11 +26,14 @@
26#include <linux/irqdomain.h> 26#include <linux/irqdomain.h>
27#include <linux/pwm.h> 27#include <linux/pwm.h>
28 28
29#include <drm/drm_atomic.h>
30#include <drm/drm_atomic_helper.h>
29#include <drm/drm_crtc.h> 31#include <drm/drm_crtc.h>
30#include <drm/drm_crtc_helper.h> 32#include <drm/drm_crtc_helper.h>
31#include <drm/drm_fb_cma_helper.h> 33#include <drm/drm_fb_cma_helper.h>
32#include <drm/drm_gem_cma_helper.h> 34#include <drm/drm_gem_cma_helper.h>
33#include <drm/drm_panel.h> 35#include <drm/drm_panel.h>
36#include <drm/drm_plane_helper.h>
34#include <drm/drmP.h> 37#include <drm/drmP.h>
35 38
36#include "atmel_hlcdc_layer.h" 39#include "atmel_hlcdc_layer.h"
@@ -69,7 +72,6 @@ struct atmel_hlcdc_dc_desc {
69 */ 72 */
70struct atmel_hlcdc_plane_properties { 73struct atmel_hlcdc_plane_properties {
71 struct drm_property *alpha; 74 struct drm_property *alpha;
72 struct drm_property *rotation;
73}; 75};
74 76
75/** 77/**
@@ -84,7 +86,6 @@ struct atmel_hlcdc_plane {
84 struct drm_plane base; 86 struct drm_plane base;
85 struct atmel_hlcdc_layer layer; 87 struct atmel_hlcdc_layer layer;
86 struct atmel_hlcdc_plane_properties *properties; 88 struct atmel_hlcdc_plane_properties *properties;
87 unsigned int rotation;
88}; 89};
89 90
90static inline struct atmel_hlcdc_plane * 91static inline struct atmel_hlcdc_plane *
@@ -100,43 +101,6 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *l)
100} 101}
101 102
102/** 103/**
103 * Atmel HLCDC Plane update request structure.
104 *
105 * @crtc_x: x position of the plane relative to the CRTC
106 * @crtc_y: y position of the plane relative to the CRTC
107 * @crtc_w: visible width of the plane
108 * @crtc_h: visible height of the plane
109 * @src_x: x buffer position
110 * @src_y: y buffer position
111 * @src_w: buffer width
112 * @src_h: buffer height
113 * @fb: framebuffer object object
114 * @bpp: bytes per pixel deduced from pixel_format
115 * @offsets: offsets to apply to the GEM buffers
116 * @xstride: value to add to the pixel pointer between each line
117 * @pstride: value to add to the pixel pointer between each pixel
118 * @nplanes: number of planes (deduced from pixel_format)
119 */
120struct atmel_hlcdc_plane_update_req {
121 int crtc_x;
122 int crtc_y;
123 unsigned int crtc_w;
124 unsigned int crtc_h;
125 uint32_t src_x;
126 uint32_t src_y;
127 uint32_t src_w;
128 uint32_t src_h;
129 struct drm_framebuffer *fb;
130
131 /* These fields are private and should not be touched */
132 int bpp[ATMEL_HLCDC_MAX_PLANES];
133 unsigned int offsets[ATMEL_HLCDC_MAX_PLANES];
134 int xstride[ATMEL_HLCDC_MAX_PLANES];
135 int pstride[ATMEL_HLCDC_MAX_PLANES];
136 int nplanes;
137};
138
139/**
140 * Atmel HLCDC Planes. 104 * Atmel HLCDC Planes.
141 * 105 *
142 * This structure stores the instantiated HLCDC Planes and can be accessed by 106 * This structure stores the instantiated HLCDC Planes and can be accessed by
@@ -184,23 +148,6 @@ int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
184struct atmel_hlcdc_planes * 148struct atmel_hlcdc_planes *
185atmel_hlcdc_create_planes(struct drm_device *dev); 149atmel_hlcdc_create_planes(struct drm_device *dev);
186 150
187int atmel_hlcdc_plane_prepare_update_req(struct drm_plane *p,
188 struct atmel_hlcdc_plane_update_req *req,
189 const struct drm_display_mode *mode);
190
191int atmel_hlcdc_plane_apply_update_req(struct drm_plane *p,
192 struct atmel_hlcdc_plane_update_req *req);
193
194int atmel_hlcdc_plane_update_with_mode(struct drm_plane *p,
195 struct drm_crtc *crtc,
196 struct drm_framebuffer *fb,
197 int crtc_x, int crtc_y,
198 unsigned int crtc_w,
199 unsigned int crtc_h,
200 uint32_t src_x, uint32_t src_y,
201 uint32_t src_w, uint32_t src_h,
202 const struct drm_display_mode *mode);
203
204void atmel_hlcdc_crtc_irq(struct drm_crtc *c); 151void atmel_hlcdc_crtc_irq(struct drm_crtc *c);
205 152
206void atmel_hlcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, 153void atmel_hlcdc_crtc_cancel_page_flip(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c
index 063d2a7b941f..d1dca39b76dd 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c
@@ -298,7 +298,7 @@ void atmel_hlcdc_layer_irq(struct atmel_hlcdc_layer *layer)
298 spin_unlock_irqrestore(&layer->lock, flags); 298 spin_unlock_irqrestore(&layer->lock, flags);
299} 299}
300 300
301int atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer) 301void atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer)
302{ 302{
303 struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma; 303 struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
304 struct atmel_hlcdc_layer_update *upd = &layer->update; 304 struct atmel_hlcdc_layer_update *upd = &layer->update;
@@ -340,8 +340,6 @@ int atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer)
340 dma->status = ATMEL_HLCDC_LAYER_DISABLED; 340 dma->status = ATMEL_HLCDC_LAYER_DISABLED;
341 341
342 spin_unlock_irqrestore(&layer->lock, flags); 342 spin_unlock_irqrestore(&layer->lock, flags);
343
344 return 0;
345} 343}
346 344
347int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer) 345int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.h
index 27e56c0862ec..9beabc940bce 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.h
@@ -120,6 +120,7 @@
120#define ATMEL_HLCDC_LAYER_DISCEN BIT(11) 120#define ATMEL_HLCDC_LAYER_DISCEN BIT(11)
121#define ATMEL_HLCDC_LAYER_GA_SHIFT 16 121#define ATMEL_HLCDC_LAYER_GA_SHIFT 16
122#define ATMEL_HLCDC_LAYER_GA_MASK GENMASK(23, ATMEL_HLCDC_LAYER_GA_SHIFT) 122#define ATMEL_HLCDC_LAYER_GA_MASK GENMASK(23, ATMEL_HLCDC_LAYER_GA_SHIFT)
123#define ATMEL_HLCDC_LAYER_GA(x) ((x) << ATMEL_HLCDC_LAYER_GA_SHIFT)
123 124
124#define ATMEL_HLCDC_LAYER_CSC_CFG(p, o) ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.csc + o) 125#define ATMEL_HLCDC_LAYER_CSC_CFG(p, o) ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.csc + o)
125 126
@@ -376,7 +377,7 @@ int atmel_hlcdc_layer_init(struct drm_device *dev,
376void atmel_hlcdc_layer_cleanup(struct drm_device *dev, 377void atmel_hlcdc_layer_cleanup(struct drm_device *dev,
377 struct atmel_hlcdc_layer *layer); 378 struct atmel_hlcdc_layer *layer);
378 379
379int atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer); 380void atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer);
380 381
381int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer); 382int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer);
382 383
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index c402192362c5..9c4513005310 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -86,25 +86,22 @@ atmel_hlcdc_rgb_output_to_panel(struct atmel_hlcdc_rgb_output *output)
86 return container_of(output, struct atmel_hlcdc_panel, base); 86 return container_of(output, struct atmel_hlcdc_panel, base);
87} 87}
88 88
89static void atmel_hlcdc_panel_encoder_dpms(struct drm_encoder *encoder, 89static void atmel_hlcdc_panel_encoder_enable(struct drm_encoder *encoder)
90 int mode)
91{ 90{
92 struct atmel_hlcdc_rgb_output *rgb = 91 struct atmel_hlcdc_rgb_output *rgb =
93 drm_encoder_to_atmel_hlcdc_rgb_output(encoder); 92 drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
94 struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb); 93 struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
95 94
96 if (mode != DRM_MODE_DPMS_ON) 95 drm_panel_enable(panel->panel);
97 mode = DRM_MODE_DPMS_OFF; 96}
98
99 if (mode == rgb->dpms)
100 return;
101 97
102 if (mode != DRM_MODE_DPMS_ON) 98static void atmel_hlcdc_panel_encoder_disable(struct drm_encoder *encoder)
103 drm_panel_disable(panel->panel); 99{
104 else 100 struct atmel_hlcdc_rgb_output *rgb =
105 drm_panel_enable(panel->panel); 101 drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
102 struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
106 103
107 rgb->dpms = mode; 104 drm_panel_disable(panel->panel);
108} 105}
109 106
110static bool 107static bool
@@ -115,16 +112,6 @@ atmel_hlcdc_panel_encoder_mode_fixup(struct drm_encoder *encoder,
115 return true; 112 return true;
116} 113}
117 114
118static void atmel_hlcdc_panel_encoder_prepare(struct drm_encoder *encoder)
119{
120 atmel_hlcdc_panel_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
121}
122
123static void atmel_hlcdc_panel_encoder_commit(struct drm_encoder *encoder)
124{
125 atmel_hlcdc_panel_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
126}
127
128static void 115static void
129atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder, 116atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder,
130 struct drm_display_mode *mode, 117 struct drm_display_mode *mode,
@@ -156,11 +143,10 @@ atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder,
156} 143}
157 144
158static struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = { 145static struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = {
159 .dpms = atmel_hlcdc_panel_encoder_dpms,
160 .mode_fixup = atmel_hlcdc_panel_encoder_mode_fixup, 146 .mode_fixup = atmel_hlcdc_panel_encoder_mode_fixup,
161 .prepare = atmel_hlcdc_panel_encoder_prepare,
162 .commit = atmel_hlcdc_panel_encoder_commit,
163 .mode_set = atmel_hlcdc_rgb_encoder_mode_set, 147 .mode_set = atmel_hlcdc_rgb_encoder_mode_set,
148 .disable = atmel_hlcdc_panel_encoder_disable,
149 .enable = atmel_hlcdc_panel_encoder_enable,
164}; 150};
165 151
166static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder) 152static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder)
@@ -226,10 +212,13 @@ atmel_hlcdc_panel_connector_destroy(struct drm_connector *connector)
226} 212}
227 213
228static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = { 214static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
229 .dpms = drm_helper_connector_dpms, 215 .dpms = drm_atomic_helper_connector_dpms,
230 .detect = atmel_hlcdc_panel_connector_detect, 216 .detect = atmel_hlcdc_panel_connector_detect,
231 .fill_modes = drm_helper_probe_single_connector_modes, 217 .fill_modes = drm_helper_probe_single_connector_modes,
232 .destroy = atmel_hlcdc_panel_connector_destroy, 218 .destroy = atmel_hlcdc_panel_connector_destroy,
219 .reset = drm_atomic_helper_connector_reset,
220 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
221 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
233}; 222};
234 223
235static int atmel_hlcdc_create_panel_output(struct drm_device *dev, 224static int atmel_hlcdc_create_panel_output(struct drm_device *dev,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index c5892dcfd745..6c6fcaef356d 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -19,6 +19,52 @@
19 19
20#include "atmel_hlcdc_dc.h" 20#include "atmel_hlcdc_dc.h"
21 21
22/**
23 * Atmel HLCDC Plane state structure.
24 *
25 * @base: DRM plane state
26 * @crtc_x: x position of the plane relative to the CRTC
27 * @crtc_y: y position of the plane relative to the CRTC
28 * @crtc_w: visible width of the plane
29 * @crtc_h: visible height of the plane
30 * @src_x: x buffer position
31 * @src_y: y buffer position
32 * @src_w: buffer width
33 * @src_h: buffer height
34 * @alpha: alpha blending of the plane
35 * @bpp: bytes per pixel deduced from pixel_format
36 * @offsets: offsets to apply to the GEM buffers
37 * @xstride: value to add to the pixel pointer between each line
38 * @pstride: value to add to the pixel pointer between each pixel
39 * @nplanes: number of planes (deduced from pixel_format)
40 */
41struct atmel_hlcdc_plane_state {
42 struct drm_plane_state base;
43 int crtc_x;
44 int crtc_y;
45 unsigned int crtc_w;
46 unsigned int crtc_h;
47 uint32_t src_x;
48 uint32_t src_y;
49 uint32_t src_w;
50 uint32_t src_h;
51
52 u8 alpha;
53
54 /* These fields are private and should not be touched */
55 int bpp[ATMEL_HLCDC_MAX_PLANES];
56 unsigned int offsets[ATMEL_HLCDC_MAX_PLANES];
57 int xstride[ATMEL_HLCDC_MAX_PLANES];
58 int pstride[ATMEL_HLCDC_MAX_PLANES];
59 int nplanes;
60};
61
62static inline struct atmel_hlcdc_plane_state *
63drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s)
64{
65 return container_of(s, struct atmel_hlcdc_plane_state, base);
66}
67
22#define SUBPIXEL_MASK 0xffff 68#define SUBPIXEL_MASK 0xffff
23 69
24static uint32_t rgb_formats[] = { 70static uint32_t rgb_formats[] = {
@@ -128,7 +174,7 @@ static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode)
128 return 0; 174 return 0;
129} 175}
130 176
131static bool atmel_hlcdc_format_embedds_alpha(u32 format) 177static bool atmel_hlcdc_format_embeds_alpha(u32 format)
132{ 178{
133 int i; 179 int i;
134 180
@@ -204,7 +250,7 @@ static u32 heo_upscaling_ycoef[] = {
204 250
205static void 251static void
206atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, 252atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
207 struct atmel_hlcdc_plane_update_req *req) 253 struct atmel_hlcdc_plane_state *state)
208{ 254{
209 const struct atmel_hlcdc_layer_cfg_layout *layout = 255 const struct atmel_hlcdc_layer_cfg_layout *layout =
210 &plane->layer.desc->layout; 256 &plane->layer.desc->layout;
@@ -213,69 +259,69 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
213 atmel_hlcdc_layer_update_cfg(&plane->layer, 259 atmel_hlcdc_layer_update_cfg(&plane->layer,
214 layout->size, 260 layout->size,
215 0xffffffff, 261 0xffffffff,
216 (req->crtc_w - 1) | 262 (state->crtc_w - 1) |
217 ((req->crtc_h - 1) << 16)); 263 ((state->crtc_h - 1) << 16));
218 264
219 if (layout->memsize) 265 if (layout->memsize)
220 atmel_hlcdc_layer_update_cfg(&plane->layer, 266 atmel_hlcdc_layer_update_cfg(&plane->layer,
221 layout->memsize, 267 layout->memsize,
222 0xffffffff, 268 0xffffffff,
223 (req->src_w - 1) | 269 (state->src_w - 1) |
224 ((req->src_h - 1) << 16)); 270 ((state->src_h - 1) << 16));
225 271
226 if (layout->pos) 272 if (layout->pos)
227 atmel_hlcdc_layer_update_cfg(&plane->layer, 273 atmel_hlcdc_layer_update_cfg(&plane->layer,
228 layout->pos, 274 layout->pos,
229 0xffffffff, 275 0xffffffff,
230 req->crtc_x | 276 state->crtc_x |
231 (req->crtc_y << 16)); 277 (state->crtc_y << 16));
232 278
233 /* TODO: rework the rescaling part */ 279 /* TODO: rework the rescaling part */
234 if (req->crtc_w != req->src_w || req->crtc_h != req->src_h) { 280 if (state->crtc_w != state->src_w || state->crtc_h != state->src_h) {
235 u32 factor_reg = 0; 281 u32 factor_reg = 0;
236 282
237 if (req->crtc_w != req->src_w) { 283 if (state->crtc_w != state->src_w) {
238 int i; 284 int i;
239 u32 factor; 285 u32 factor;
240 u32 *coeff_tab = heo_upscaling_xcoef; 286 u32 *coeff_tab = heo_upscaling_xcoef;
241 u32 max_memsize; 287 u32 max_memsize;
242 288
243 if (req->crtc_w < req->src_w) 289 if (state->crtc_w < state->src_w)
244 coeff_tab = heo_downscaling_xcoef; 290 coeff_tab = heo_downscaling_xcoef;
245 for (i = 0; i < ARRAY_SIZE(heo_upscaling_xcoef); i++) 291 for (i = 0; i < ARRAY_SIZE(heo_upscaling_xcoef); i++)
246 atmel_hlcdc_layer_update_cfg(&plane->layer, 292 atmel_hlcdc_layer_update_cfg(&plane->layer,
247 17 + i, 293 17 + i,
248 0xffffffff, 294 0xffffffff,
249 coeff_tab[i]); 295 coeff_tab[i]);
250 factor = ((8 * 256 * req->src_w) - (256 * 4)) / 296 factor = ((8 * 256 * state->src_w) - (256 * 4)) /
251 req->crtc_w; 297 state->crtc_w;
252 factor++; 298 factor++;
253 max_memsize = ((factor * req->crtc_w) + (256 * 4)) / 299 max_memsize = ((factor * state->crtc_w) + (256 * 4)) /
254 2048; 300 2048;
255 if (max_memsize > req->src_w) 301 if (max_memsize > state->src_w)
256 factor--; 302 factor--;
257 factor_reg |= factor | 0x80000000; 303 factor_reg |= factor | 0x80000000;
258 } 304 }
259 305
260 if (req->crtc_h != req->src_h) { 306 if (state->crtc_h != state->src_h) {
261 int i; 307 int i;
262 u32 factor; 308 u32 factor;
263 u32 *coeff_tab = heo_upscaling_ycoef; 309 u32 *coeff_tab = heo_upscaling_ycoef;
264 u32 max_memsize; 310 u32 max_memsize;
265 311
266 if (req->crtc_w < req->src_w) 312 if (state->crtc_w < state->src_w)
267 coeff_tab = heo_downscaling_ycoef; 313 coeff_tab = heo_downscaling_ycoef;
268 for (i = 0; i < ARRAY_SIZE(heo_upscaling_ycoef); i++) 314 for (i = 0; i < ARRAY_SIZE(heo_upscaling_ycoef); i++)
269 atmel_hlcdc_layer_update_cfg(&plane->layer, 315 atmel_hlcdc_layer_update_cfg(&plane->layer,
270 33 + i, 316 33 + i,
271 0xffffffff, 317 0xffffffff,
272 coeff_tab[i]); 318 coeff_tab[i]);
273 factor = ((8 * 256 * req->src_w) - (256 * 4)) / 319 factor = ((8 * 256 * state->src_w) - (256 * 4)) /
274 req->crtc_w; 320 state->crtc_w;
275 factor++; 321 factor++;
276 max_memsize = ((factor * req->crtc_w) + (256 * 4)) / 322 max_memsize = ((factor * state->crtc_w) + (256 * 4)) /
277 2048; 323 2048;
278 if (max_memsize > req->src_w) 324 if (max_memsize > state->src_w)
279 factor--; 325 factor--;
280 factor_reg |= (factor << 16) | 0x80000000; 326 factor_reg |= (factor << 16) | 0x80000000;
281 } 327 }
@@ -287,7 +333,7 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
287 333
288static void 334static void
289atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, 335atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
290 struct atmel_hlcdc_plane_update_req *req) 336 struct atmel_hlcdc_plane_state *state)
291{ 337{
292 const struct atmel_hlcdc_layer_cfg_layout *layout = 338 const struct atmel_hlcdc_layer_cfg_layout *layout =
293 &plane->layer.desc->layout; 339 &plane->layer.desc->layout;
@@ -297,10 +343,11 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
297 cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL | 343 cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL |
298 ATMEL_HLCDC_LAYER_ITER; 344 ATMEL_HLCDC_LAYER_ITER;
299 345
300 if (atmel_hlcdc_format_embedds_alpha(req->fb->pixel_format)) 346 if (atmel_hlcdc_format_embeds_alpha(state->base.fb->pixel_format))
301 cfg |= ATMEL_HLCDC_LAYER_LAEN; 347 cfg |= ATMEL_HLCDC_LAYER_LAEN;
302 else 348 else
303 cfg |= ATMEL_HLCDC_LAYER_GAEN; 349 cfg |= ATMEL_HLCDC_LAYER_GAEN |
350 ATMEL_HLCDC_LAYER_GA(state->alpha);
304 } 351 }
305 352
306 atmel_hlcdc_layer_update_cfg(&plane->layer, 353 atmel_hlcdc_layer_update_cfg(&plane->layer,
@@ -312,24 +359,26 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
312 ATMEL_HLCDC_LAYER_ITER2BL | 359 ATMEL_HLCDC_LAYER_ITER2BL |
313 ATMEL_HLCDC_LAYER_ITER | 360 ATMEL_HLCDC_LAYER_ITER |
314 ATMEL_HLCDC_LAYER_GAEN | 361 ATMEL_HLCDC_LAYER_GAEN |
362 ATMEL_HLCDC_LAYER_GA_MASK |
315 ATMEL_HLCDC_LAYER_LAEN | 363 ATMEL_HLCDC_LAYER_LAEN |
316 ATMEL_HLCDC_LAYER_OVR | 364 ATMEL_HLCDC_LAYER_OVR |
317 ATMEL_HLCDC_LAYER_DMA, cfg); 365 ATMEL_HLCDC_LAYER_DMA, cfg);
318} 366}
319 367
320static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, 368static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
321 struct atmel_hlcdc_plane_update_req *req) 369 struct atmel_hlcdc_plane_state *state)
322{ 370{
323 u32 cfg; 371 u32 cfg;
324 int ret; 372 int ret;
325 373
326 ret = atmel_hlcdc_format_to_plane_mode(req->fb->pixel_format, &cfg); 374 ret = atmel_hlcdc_format_to_plane_mode(state->base.fb->pixel_format,
375 &cfg);
327 if (ret) 376 if (ret)
328 return; 377 return;
329 378
330 if ((req->fb->pixel_format == DRM_FORMAT_YUV422 || 379 if ((state->base.fb->pixel_format == DRM_FORMAT_YUV422 ||
331 req->fb->pixel_format == DRM_FORMAT_NV61) && 380 state->base.fb->pixel_format == DRM_FORMAT_NV61) &&
332 (plane->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270)))) 381 (state->base.rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))))
333 cfg |= ATMEL_HLCDC_YUV422ROT; 382 cfg |= ATMEL_HLCDC_YUV422ROT;
334 383
335 atmel_hlcdc_layer_update_cfg(&plane->layer, 384 atmel_hlcdc_layer_update_cfg(&plane->layer,
@@ -341,7 +390,7 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
341 * Rotation optimization is not working on RGB888 (rotation is still 390 * Rotation optimization is not working on RGB888 (rotation is still
342 * working but without any optimization). 391 * working but without any optimization).
343 */ 392 */
344 if (req->fb->pixel_format == DRM_FORMAT_RGB888) 393 if (state->base.fb->pixel_format == DRM_FORMAT_RGB888)
345 cfg = ATMEL_HLCDC_LAYER_DMA_ROTDIS; 394 cfg = ATMEL_HLCDC_LAYER_DMA_ROTDIS;
346 else 395 else
347 cfg = 0; 396 cfg = 0;
@@ -352,73 +401,44 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
352} 401}
353 402
354static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, 403static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
355 struct atmel_hlcdc_plane_update_req *req) 404 struct atmel_hlcdc_plane_state *state)
356{ 405{
357 struct atmel_hlcdc_layer *layer = &plane->layer; 406 struct atmel_hlcdc_layer *layer = &plane->layer;
358 const struct atmel_hlcdc_layer_cfg_layout *layout = 407 const struct atmel_hlcdc_layer_cfg_layout *layout =
359 &layer->desc->layout; 408 &layer->desc->layout;
360 int i; 409 int i;
361 410
362 atmel_hlcdc_layer_update_set_fb(&plane->layer, req->fb, req->offsets); 411 atmel_hlcdc_layer_update_set_fb(&plane->layer, state->base.fb,
412 state->offsets);
363 413
364 for (i = 0; i < req->nplanes; i++) { 414 for (i = 0; i < state->nplanes; i++) {
365 if (layout->xstride[i]) { 415 if (layout->xstride[i]) {
366 atmel_hlcdc_layer_update_cfg(&plane->layer, 416 atmel_hlcdc_layer_update_cfg(&plane->layer,
367 layout->xstride[i], 417 layout->xstride[i],
368 0xffffffff, 418 0xffffffff,
369 req->xstride[i]); 419 state->xstride[i]);
370 } 420 }
371 421
372 if (layout->pstride[i]) { 422 if (layout->pstride[i]) {
373 atmel_hlcdc_layer_update_cfg(&plane->layer, 423 atmel_hlcdc_layer_update_cfg(&plane->layer,
374 layout->pstride[i], 424 layout->pstride[i],
375 0xffffffff, 425 0xffffffff,
376 req->pstride[i]); 426 state->pstride[i]);
377 } 427 }
378 } 428 }
379} 429}
380 430
381static int atmel_hlcdc_plane_check_update_req(struct drm_plane *p, 431static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
382 struct atmel_hlcdc_plane_update_req *req, 432 struct drm_plane_state *s)
383 const struct drm_display_mode *mode)
384{ 433{
385 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 434 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
435 struct atmel_hlcdc_plane_state *state =
436 drm_plane_state_to_atmel_hlcdc_plane_state(s);
386 const struct atmel_hlcdc_layer_cfg_layout *layout = 437 const struct atmel_hlcdc_layer_cfg_layout *layout =
387 &plane->layer.desc->layout; 438 &plane->layer.desc->layout;
388 439 struct drm_framebuffer *fb = state->base.fb;
389 if (!layout->size && 440 const struct drm_display_mode *mode;
390 (mode->hdisplay != req->crtc_w || 441 struct drm_crtc_state *crtc_state;
391 mode->vdisplay != req->crtc_h))
392 return -EINVAL;
393
394 if (plane->layer.desc->max_height &&
395 req->crtc_h > plane->layer.desc->max_height)
396 return -EINVAL;
397
398 if (plane->layer.desc->max_width &&
399 req->crtc_w > plane->layer.desc->max_width)
400 return -EINVAL;
401
402 if ((req->crtc_h != req->src_h || req->crtc_w != req->src_w) &&
403 (!layout->memsize ||
404 atmel_hlcdc_format_embedds_alpha(req->fb->pixel_format)))
405 return -EINVAL;
406
407 if (req->crtc_x < 0 || req->crtc_y < 0)
408 return -EINVAL;
409
410 if (req->crtc_w + req->crtc_x > mode->hdisplay ||
411 req->crtc_h + req->crtc_y > mode->vdisplay)
412 return -EINVAL;
413
414 return 0;
415}
416
417int atmel_hlcdc_plane_prepare_update_req(struct drm_plane *p,
418 struct atmel_hlcdc_plane_update_req *req,
419 const struct drm_display_mode *mode)
420{
421 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
422 unsigned int patched_crtc_w; 442 unsigned int patched_crtc_w;
423 unsigned int patched_crtc_h; 443 unsigned int patched_crtc_h;
424 unsigned int patched_src_w; 444 unsigned int patched_src_w;
@@ -430,196 +450,194 @@ int atmel_hlcdc_plane_prepare_update_req(struct drm_plane *p,
430 int vsub = 1; 450 int vsub = 1;
431 int i; 451 int i;
432 452
433 if ((req->src_x | req->src_y | req->src_w | req->src_h) & 453 if (!state->base.crtc || !fb)
454 return 0;
455
456 crtc_state = s->state->crtc_states[drm_crtc_index(s->crtc)];
457 mode = &crtc_state->adjusted_mode;
458
459 state->src_x = s->src_x;
460 state->src_y = s->src_y;
461 state->src_h = s->src_h;
462 state->src_w = s->src_w;
463 state->crtc_x = s->crtc_x;
464 state->crtc_y = s->crtc_y;
465 state->crtc_h = s->crtc_h;
466 state->crtc_w = s->crtc_w;
467 if ((state->src_x | state->src_y | state->src_w | state->src_h) &
434 SUBPIXEL_MASK) 468 SUBPIXEL_MASK)
435 return -EINVAL; 469 return -EINVAL;
436 470
437 req->src_x >>= 16; 471 state->src_x >>= 16;
438 req->src_y >>= 16; 472 state->src_y >>= 16;
439 req->src_w >>= 16; 473 state->src_w >>= 16;
440 req->src_h >>= 16; 474 state->src_h >>= 16;
441 475
442 req->nplanes = drm_format_num_planes(req->fb->pixel_format); 476 state->nplanes = drm_format_num_planes(fb->pixel_format);
443 if (req->nplanes > ATMEL_HLCDC_MAX_PLANES) 477 if (state->nplanes > ATMEL_HLCDC_MAX_PLANES)
444 return -EINVAL; 478 return -EINVAL;
445 479
446 /* 480 /*
447 * Swap width and size in case of 90 or 270 degrees rotation 481 * Swap width and size in case of 90 or 270 degrees rotation
448 */ 482 */
449 if (plane->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) { 483 if (state->base.rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
450 tmp = req->crtc_w; 484 tmp = state->crtc_w;
451 req->crtc_w = req->crtc_h; 485 state->crtc_w = state->crtc_h;
452 req->crtc_h = tmp; 486 state->crtc_h = tmp;
453 tmp = req->src_w; 487 tmp = state->src_w;
454 req->src_w = req->src_h; 488 state->src_w = state->src_h;
455 req->src_h = tmp; 489 state->src_h = tmp;
456 } 490 }
457 491
458 if (req->crtc_x + req->crtc_w > mode->hdisplay) 492 if (state->crtc_x + state->crtc_w > mode->hdisplay)
459 patched_crtc_w = mode->hdisplay - req->crtc_x; 493 patched_crtc_w = mode->hdisplay - state->crtc_x;
460 else 494 else
461 patched_crtc_w = req->crtc_w; 495 patched_crtc_w = state->crtc_w;
462 496
463 if (req->crtc_x < 0) { 497 if (state->crtc_x < 0) {
464 patched_crtc_w += req->crtc_x; 498 patched_crtc_w += state->crtc_x;
465 x_offset = -req->crtc_x; 499 x_offset = -state->crtc_x;
466 req->crtc_x = 0; 500 state->crtc_x = 0;
467 } 501 }
468 502
469 if (req->crtc_y + req->crtc_h > mode->vdisplay) 503 if (state->crtc_y + state->crtc_h > mode->vdisplay)
470 patched_crtc_h = mode->vdisplay - req->crtc_y; 504 patched_crtc_h = mode->vdisplay - state->crtc_y;
471 else 505 else
472 patched_crtc_h = req->crtc_h; 506 patched_crtc_h = state->crtc_h;
473 507
474 if (req->crtc_y < 0) { 508 if (state->crtc_y < 0) {
475 patched_crtc_h += req->crtc_y; 509 patched_crtc_h += state->crtc_y;
476 y_offset = -req->crtc_y; 510 y_offset = -state->crtc_y;
477 req->crtc_y = 0; 511 state->crtc_y = 0;
478 } 512 }
479 513
480 patched_src_w = DIV_ROUND_CLOSEST(patched_crtc_w * req->src_w, 514 patched_src_w = DIV_ROUND_CLOSEST(patched_crtc_w * state->src_w,
481 req->crtc_w); 515 state->crtc_w);
482 patched_src_h = DIV_ROUND_CLOSEST(patched_crtc_h * req->src_h, 516 patched_src_h = DIV_ROUND_CLOSEST(patched_crtc_h * state->src_h,
483 req->crtc_h); 517 state->crtc_h);
484 518
485 hsub = drm_format_horz_chroma_subsampling(req->fb->pixel_format); 519 hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
486 vsub = drm_format_vert_chroma_subsampling(req->fb->pixel_format); 520 vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
487 521
488 for (i = 0; i < req->nplanes; i++) { 522 for (i = 0; i < state->nplanes; i++) {
489 unsigned int offset = 0; 523 unsigned int offset = 0;
490 int xdiv = i ? hsub : 1; 524 int xdiv = i ? hsub : 1;
491 int ydiv = i ? vsub : 1; 525 int ydiv = i ? vsub : 1;
492 526
493 req->bpp[i] = drm_format_plane_cpp(req->fb->pixel_format, i); 527 state->bpp[i] = drm_format_plane_cpp(fb->pixel_format, i);
494 if (!req->bpp[i]) 528 if (!state->bpp[i])
495 return -EINVAL; 529 return -EINVAL;
496 530
497 switch (plane->rotation & 0xf) { 531 switch (state->base.rotation & 0xf) {
498 case BIT(DRM_ROTATE_90): 532 case BIT(DRM_ROTATE_90):
499 offset = ((y_offset + req->src_y + patched_src_w - 1) / 533 offset = ((y_offset + state->src_y + patched_src_w - 1) /
500 ydiv) * req->fb->pitches[i]; 534 ydiv) * fb->pitches[i];
501 offset += ((x_offset + req->src_x) / xdiv) * 535 offset += ((x_offset + state->src_x) / xdiv) *
502 req->bpp[i]; 536 state->bpp[i];
503 req->xstride[i] = ((patched_src_w - 1) / ydiv) * 537 state->xstride[i] = ((patched_src_w - 1) / ydiv) *
504 req->fb->pitches[i]; 538 fb->pitches[i];
505 req->pstride[i] = -req->fb->pitches[i] - req->bpp[i]; 539 state->pstride[i] = -fb->pitches[i] - state->bpp[i];
506 break; 540 break;
507 case BIT(DRM_ROTATE_180): 541 case BIT(DRM_ROTATE_180):
508 offset = ((y_offset + req->src_y + patched_src_h - 1) / 542 offset = ((y_offset + state->src_y + patched_src_h - 1) /
509 ydiv) * req->fb->pitches[i]; 543 ydiv) * fb->pitches[i];
510 offset += ((x_offset + req->src_x + patched_src_w - 1) / 544 offset += ((x_offset + state->src_x + patched_src_w - 1) /
511 xdiv) * req->bpp[i]; 545 xdiv) * state->bpp[i];
512 req->xstride[i] = ((((patched_src_w - 1) / xdiv) - 1) * 546 state->xstride[i] = ((((patched_src_w - 1) / xdiv) - 1) *
513 req->bpp[i]) - req->fb->pitches[i]; 547 state->bpp[i]) - fb->pitches[i];
514 req->pstride[i] = -2 * req->bpp[i]; 548 state->pstride[i] = -2 * state->bpp[i];
515 break; 549 break;
516 case BIT(DRM_ROTATE_270): 550 case BIT(DRM_ROTATE_270):
517 offset = ((y_offset + req->src_y) / ydiv) * 551 offset = ((y_offset + state->src_y) / ydiv) *
518 req->fb->pitches[i]; 552 fb->pitches[i];
519 offset += ((x_offset + req->src_x + patched_src_h - 1) / 553 offset += ((x_offset + state->src_x + patched_src_h - 1) /
520 xdiv) * req->bpp[i]; 554 xdiv) * state->bpp[i];
521 req->xstride[i] = -(((patched_src_w - 1) / ydiv) * 555 state->xstride[i] = -(((patched_src_w - 1) / ydiv) *
522 req->fb->pitches[i]) - 556 fb->pitches[i]) -
523 (2 * req->bpp[i]); 557 (2 * state->bpp[i]);
524 req->pstride[i] = req->fb->pitches[i] - req->bpp[i]; 558 state->pstride[i] = fb->pitches[i] - state->bpp[i];
525 break; 559 break;
526 case BIT(DRM_ROTATE_0): 560 case BIT(DRM_ROTATE_0):
527 default: 561 default:
528 offset = ((y_offset + req->src_y) / ydiv) * 562 offset = ((y_offset + state->src_y) / ydiv) *
529 req->fb->pitches[i]; 563 fb->pitches[i];
530 offset += ((x_offset + req->src_x) / xdiv) * 564 offset += ((x_offset + state->src_x) / xdiv) *
531 req->bpp[i]; 565 state->bpp[i];
532 req->xstride[i] = req->fb->pitches[i] - 566 state->xstride[i] = fb->pitches[i] -
533 ((patched_src_w / xdiv) * 567 ((patched_src_w / xdiv) *
534 req->bpp[i]); 568 state->bpp[i]);
535 req->pstride[i] = 0; 569 state->pstride[i] = 0;
536 break; 570 break;
537 } 571 }
538 572
539 req->offsets[i] = offset + req->fb->offsets[i]; 573 state->offsets[i] = offset + fb->offsets[i];
540 } 574 }
541 575
542 req->src_w = patched_src_w; 576 state->src_w = patched_src_w;
543 req->src_h = patched_src_h; 577 state->src_h = patched_src_h;
544 req->crtc_w = patched_crtc_w; 578 state->crtc_w = patched_crtc_w;
545 req->crtc_h = patched_crtc_h; 579 state->crtc_h = patched_crtc_h;
546 580
547 return atmel_hlcdc_plane_check_update_req(p, req, mode); 581 if (!layout->size &&
548} 582 (mode->hdisplay != state->crtc_w ||
583 mode->vdisplay != state->crtc_h))
584 return -EINVAL;
549 585
550int atmel_hlcdc_plane_apply_update_req(struct drm_plane *p, 586 if (plane->layer.desc->max_height &&
551 struct atmel_hlcdc_plane_update_req *req) 587 state->crtc_h > plane->layer.desc->max_height)
552{ 588 return -EINVAL;
553 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
554 int ret;
555 589
556 ret = atmel_hlcdc_layer_update_start(&plane->layer); 590 if (plane->layer.desc->max_width &&
557 if (ret) 591 state->crtc_w > plane->layer.desc->max_width)
558 return ret; 592 return -EINVAL;
559 593
560 atmel_hlcdc_plane_update_pos_and_size(plane, req); 594 if ((state->crtc_h != state->src_h || state->crtc_w != state->src_w) &&
561 atmel_hlcdc_plane_update_general_settings(plane, req); 595 (!layout->memsize ||
562 atmel_hlcdc_plane_update_format(plane, req); 596 atmel_hlcdc_format_embeds_alpha(state->base.fb->pixel_format)))
563 atmel_hlcdc_plane_update_buffers(plane, req); 597 return -EINVAL;
564 598
565 atmel_hlcdc_layer_update_commit(&plane->layer); 599 if (state->crtc_x < 0 || state->crtc_y < 0)
600 return -EINVAL;
601
602 if (state->crtc_w + state->crtc_x > mode->hdisplay ||
603 state->crtc_h + state->crtc_y > mode->vdisplay)
604 return -EINVAL;
566 605
567 return 0; 606 return 0;
568} 607}
569 608
570int atmel_hlcdc_plane_update_with_mode(struct drm_plane *p, 609static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
571 struct drm_crtc *crtc, 610 struct drm_framebuffer *fb)
572 struct drm_framebuffer *fb,
573 int crtc_x, int crtc_y,
574 unsigned int crtc_w,
575 unsigned int crtc_h,
576 uint32_t src_x, uint32_t src_y,
577 uint32_t src_w, uint32_t src_h,
578 const struct drm_display_mode *mode)
579{ 611{
580 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 612 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
581 struct atmel_hlcdc_plane_update_req req;
582 int ret = 0;
583
584 memset(&req, 0, sizeof(req));
585 req.crtc_x = crtc_x;
586 req.crtc_y = crtc_y;
587 req.crtc_w = crtc_w;
588 req.crtc_h = crtc_h;
589 req.src_x = src_x;
590 req.src_y = src_y;
591 req.src_w = src_w;
592 req.src_h = src_h;
593 req.fb = fb;
594
595 ret = atmel_hlcdc_plane_prepare_update_req(&plane->base, &req, mode);
596 if (ret)
597 return ret;
598 613
599 if (!req.crtc_h || !req.crtc_w) 614 return atmel_hlcdc_layer_update_start(&plane->layer);
600 return atmel_hlcdc_layer_disable(&plane->layer);
601
602 return atmel_hlcdc_plane_apply_update_req(&plane->base, &req);
603} 615}
604 616
605static int atmel_hlcdc_plane_update(struct drm_plane *p, 617static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
606 struct drm_crtc *crtc, 618 struct drm_plane_state *old_s)
607 struct drm_framebuffer *fb,
608 int crtc_x, int crtc_y,
609 unsigned int crtc_w, unsigned int crtc_h,
610 uint32_t src_x, uint32_t src_y,
611 uint32_t src_w, uint32_t src_h)
612{ 619{
613 return atmel_hlcdc_plane_update_with_mode(p, crtc, fb, crtc_x, crtc_y, 620 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
614 crtc_w, crtc_h, src_x, src_y, 621 struct atmel_hlcdc_plane_state *state =
615 src_w, src_h, &crtc->hwmode); 622 drm_plane_state_to_atmel_hlcdc_plane_state(p->state);
623
624 if (!p->state->crtc || !p->state->fb)
625 return;
626
627 atmel_hlcdc_plane_update_pos_and_size(plane, state);
628 atmel_hlcdc_plane_update_general_settings(plane, state);
629 atmel_hlcdc_plane_update_format(plane, state);
630 atmel_hlcdc_plane_update_buffers(plane, state);
631
632 atmel_hlcdc_layer_update_commit(&plane->layer);
616} 633}
617 634
618static int atmel_hlcdc_plane_disable(struct drm_plane *p) 635static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
636 struct drm_plane_state *old_state)
619{ 637{
620 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 638 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
621 639
622 return atmel_hlcdc_layer_disable(&plane->layer); 640 atmel_hlcdc_layer_disable(&plane->layer);
623} 641}
624 642
625static void atmel_hlcdc_plane_destroy(struct drm_plane *p) 643static void atmel_hlcdc_plane_destroy(struct drm_plane *p)
@@ -635,38 +653,36 @@ static void atmel_hlcdc_plane_destroy(struct drm_plane *p)
635 devm_kfree(p->dev->dev, plane); 653 devm_kfree(p->dev->dev, plane);
636} 654}
637 655
638static int atmel_hlcdc_plane_set_alpha(struct atmel_hlcdc_plane *plane, 656static int atmel_hlcdc_plane_atomic_set_property(struct drm_plane *p,
639 u8 alpha) 657 struct drm_plane_state *s,
658 struct drm_property *property,
659 uint64_t val)
640{ 660{
641 atmel_hlcdc_layer_update_start(&plane->layer); 661 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
642 atmel_hlcdc_layer_update_cfg(&plane->layer, 662 struct atmel_hlcdc_plane_properties *props = plane->properties;
643 plane->layer.desc->layout.general_config, 663 struct atmel_hlcdc_plane_state *state =
644 ATMEL_HLCDC_LAYER_GA_MASK, 664 drm_plane_state_to_atmel_hlcdc_plane_state(s);
645 alpha << ATMEL_HLCDC_LAYER_GA_SHIFT);
646 atmel_hlcdc_layer_update_commit(&plane->layer);
647
648 return 0;
649}
650 665
651static int atmel_hlcdc_plane_set_rotation(struct atmel_hlcdc_plane *plane, 666 if (property == props->alpha)
652 unsigned int rotation) 667 state->alpha = val;
653{ 668 else
654 plane->rotation = rotation; 669 return -EINVAL;
655 670
656 return 0; 671 return 0;
657} 672}
658 673
659static int atmel_hlcdc_plane_set_property(struct drm_plane *p, 674static int atmel_hlcdc_plane_atomic_get_property(struct drm_plane *p,
660 struct drm_property *property, 675 const struct drm_plane_state *s,
661 uint64_t value) 676 struct drm_property *property,
677 uint64_t *val)
662{ 678{
663 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 679 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
664 struct atmel_hlcdc_plane_properties *props = plane->properties; 680 struct atmel_hlcdc_plane_properties *props = plane->properties;
681 const struct atmel_hlcdc_plane_state *state =
682 container_of(s, const struct atmel_hlcdc_plane_state, base);
665 683
666 if (property == props->alpha) 684 if (property == props->alpha)
667 atmel_hlcdc_plane_set_alpha(plane, value); 685 *val = state->alpha;
668 else if (property == props->rotation)
669 atmel_hlcdc_plane_set_rotation(plane, value);
670 else 686 else
671 return -EINVAL; 687 return -EINVAL;
672 688
@@ -694,8 +710,8 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
694 710
695 if (desc->layout.xstride && desc->layout.pstride) 711 if (desc->layout.xstride && desc->layout.pstride)
696 drm_object_attach_property(&plane->base.base, 712 drm_object_attach_property(&plane->base.base,
697 props->rotation, 713 plane->base.dev->mode_config.rotation_property,
698 BIT(DRM_ROTATE_0)); 714 BIT(DRM_ROTATE_0));
699 715
700 if (desc->layout.csc) { 716 if (desc->layout.csc) {
701 /* 717 /*
@@ -717,11 +733,74 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
717 } 733 }
718} 734}
719 735
736static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
737 .prepare_fb = atmel_hlcdc_plane_prepare_fb,
738 .atomic_check = atmel_hlcdc_plane_atomic_check,
739 .atomic_update = atmel_hlcdc_plane_atomic_update,
740 .atomic_disable = atmel_hlcdc_plane_atomic_disable,
741};
742
743static void atmel_hlcdc_plane_reset(struct drm_plane *p)
744{
745 struct atmel_hlcdc_plane_state *state;
746
747 if (p->state) {
748 state = drm_plane_state_to_atmel_hlcdc_plane_state(p->state);
749
750 if (state->base.fb)
751 drm_framebuffer_unreference(state->base.fb);
752
753 kfree(state);
754 p->state = NULL;
755 }
756
757 state = kzalloc(sizeof(*state), GFP_KERNEL);
758 if (state) {
759 state->alpha = 255;
760 p->state = &state->base;
761 p->state->plane = p;
762 }
763}
764
765static struct drm_plane_state *
766atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p)
767{
768 struct atmel_hlcdc_plane_state *state =
769 drm_plane_state_to_atmel_hlcdc_plane_state(p->state);
770 struct atmel_hlcdc_plane_state *copy;
771
772 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
773 if (!copy)
774 return NULL;
775
776 if (copy->base.fb)
777 drm_framebuffer_reference(copy->base.fb);
778
779 return &copy->base;
780}
781
782static void atmel_hlcdc_plane_atomic_destroy_state(struct drm_plane *plane,
783 struct drm_plane_state *s)
784{
785 struct atmel_hlcdc_plane_state *state =
786 drm_plane_state_to_atmel_hlcdc_plane_state(s);
787
788 if (s->fb)
789 drm_framebuffer_unreference(s->fb);
790
791 kfree(state);
792}
793
720static struct drm_plane_funcs layer_plane_funcs = { 794static struct drm_plane_funcs layer_plane_funcs = {
721 .update_plane = atmel_hlcdc_plane_update, 795 .update_plane = drm_atomic_helper_update_plane,
722 .disable_plane = atmel_hlcdc_plane_disable, 796 .disable_plane = drm_atomic_helper_disable_plane,
723 .set_property = atmel_hlcdc_plane_set_property, 797 .set_property = drm_atomic_helper_plane_set_property,
724 .destroy = atmel_hlcdc_plane_destroy, 798 .destroy = atmel_hlcdc_plane_destroy,
799 .reset = atmel_hlcdc_plane_reset,
800 .atomic_duplicate_state = atmel_hlcdc_plane_atomic_duplicate_state,
801 .atomic_destroy_state = atmel_hlcdc_plane_atomic_destroy_state,
802 .atomic_set_property = atmel_hlcdc_plane_atomic_set_property,
803 .atomic_get_property = atmel_hlcdc_plane_atomic_get_property,
725}; 804};
726 805
727static struct atmel_hlcdc_plane * 806static struct atmel_hlcdc_plane *
@@ -755,6 +834,9 @@ atmel_hlcdc_plane_create(struct drm_device *dev,
755 if (ret) 834 if (ret)
756 return ERR_PTR(ret); 835 return ERR_PTR(ret);
757 836
837 drm_plane_helper_add(&plane->base,
838 &atmel_hlcdc_layer_plane_helper_funcs);
839
758 /* Set default property values*/ 840 /* Set default property values*/
759 atmel_hlcdc_plane_init_properties(plane, desc, props); 841 atmel_hlcdc_plane_init_properties(plane, desc, props);
760 842
@@ -774,12 +856,13 @@ atmel_hlcdc_plane_create_properties(struct drm_device *dev)
774 if (!props->alpha) 856 if (!props->alpha)
775 return ERR_PTR(-ENOMEM); 857 return ERR_PTR(-ENOMEM);
776 858
777 props->rotation = drm_mode_create_rotation_property(dev, 859 dev->mode_config.rotation_property =
778 BIT(DRM_ROTATE_0) | 860 drm_mode_create_rotation_property(dev,
779 BIT(DRM_ROTATE_90) | 861 BIT(DRM_ROTATE_0) |
780 BIT(DRM_ROTATE_180) | 862 BIT(DRM_ROTATE_90) |
781 BIT(DRM_ROTATE_270)); 863 BIT(DRM_ROTATE_180) |
782 if (!props->rotation) 864 BIT(DRM_ROTATE_270));
865 if (!dev->mode_config.rotation_property)
783 return ERR_PTR(-ENOMEM); 866 return ERR_PTR(-ENOMEM);
784 867
785 return props; 868 return props;