Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

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