1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2014 Free Electrons 4 * Copyright (C) 2014 Atmel 5 * 6 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> 7 */ 8 9 #include <linux/dmapool.h> 10 #include <linux/mfd/atmel-hlcdc.h> 11 12 #include <drm/drm_atomic.h> 13 #include <drm/drm_atomic_helper.h> 14 #include <drm/drm_blend.h> 15 #include <drm/drm_fb_dma_helper.h> 16 #include <drm/drm_fourcc.h> 17 #include <drm/drm_framebuffer.h> 18 #include <drm/drm_gem_dma_helper.h> 19 #include <drm/drm_print.h> 20 21 #include "atmel_hlcdc_dc.h" 22 23 /** 24 * struct atmel_hlcdc_plane_state - Atmel HLCDC Plane state structure. 25 * 26 * @base: DRM plane state 27 * @crtc_x: x position of the plane relative to the CRTC 28 * @crtc_y: y position of the plane relative to the CRTC 29 * @crtc_w: visible width of the plane 30 * @crtc_h: visible height of the plane 31 * @src_x: x buffer position 32 * @src_y: y buffer position 33 * @src_w: buffer width 34 * @src_h: buffer height 35 * @disc_x: x discard position 36 * @disc_y: y discard position 37 * @disc_w: discard width 38 * @disc_h: discard height 39 * @ahb_id: AHB identification number 40 * @bpp: bytes per pixel deduced from pixel_format 41 * @offsets: offsets to apply to the GEM buffers 42 * @xstride: value to add to the pixel pointer between each line 43 * @pstride: value to add to the pixel pointer between each pixel 44 * @nplanes: number of planes (deduced from pixel_format) 45 * @dscrs: DMA descriptors 46 */ 47 struct atmel_hlcdc_plane_state { 48 struct drm_plane_state base; 49 int crtc_x; 50 int crtc_y; 51 unsigned int crtc_w; 52 unsigned int crtc_h; 53 uint32_t src_x; 54 uint32_t src_y; 55 uint32_t src_w; 56 uint32_t src_h; 57 58 int disc_x; 59 int disc_y; 60 int disc_w; 61 int disc_h; 62 63 int ahb_id; 64 65 /* These fields are private and should not be touched */ 66 int bpp[ATMEL_HLCDC_LAYER_MAX_PLANES]; 67 unsigned int offsets[ATMEL_HLCDC_LAYER_MAX_PLANES]; 68 int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES]; 69 int pstride[ATMEL_HLCDC_LAYER_MAX_PLANES]; 70 int nplanes; 71 72 /* DMA descriptors. */ 73 struct atmel_hlcdc_dma_channel_dscr *dscrs[ATMEL_HLCDC_LAYER_MAX_PLANES]; 74 }; 75 76 static inline struct atmel_hlcdc_plane_state * 77 drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s) 78 { 79 return container_of(s, struct atmel_hlcdc_plane_state, base); 80 } 81 82 #define SUBPIXEL_MASK 0xffff 83 84 static uint32_t rgb_formats[] = { 85 DRM_FORMAT_C8, 86 DRM_FORMAT_XRGB4444, 87 DRM_FORMAT_ARGB4444, 88 DRM_FORMAT_RGBA4444, 89 DRM_FORMAT_ARGB1555, 90 DRM_FORMAT_RGB565, 91 DRM_FORMAT_RGB888, 92 DRM_FORMAT_XRGB8888, 93 DRM_FORMAT_ARGB8888, 94 DRM_FORMAT_RGBA8888, 95 }; 96 97 struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = { 98 .formats = rgb_formats, 99 .nformats = ARRAY_SIZE(rgb_formats), 100 }; 101 102 static uint32_t rgb_and_yuv_formats[] = { 103 DRM_FORMAT_C8, 104 DRM_FORMAT_XRGB4444, 105 DRM_FORMAT_ARGB4444, 106 DRM_FORMAT_RGBA4444, 107 DRM_FORMAT_ARGB1555, 108 DRM_FORMAT_RGB565, 109 DRM_FORMAT_RGB888, 110 DRM_FORMAT_XRGB8888, 111 DRM_FORMAT_ARGB8888, 112 DRM_FORMAT_RGBA8888, 113 DRM_FORMAT_AYUV, 114 DRM_FORMAT_YUYV, 115 DRM_FORMAT_UYVY, 116 DRM_FORMAT_YVYU, 117 DRM_FORMAT_VYUY, 118 DRM_FORMAT_NV21, 119 DRM_FORMAT_NV61, 120 DRM_FORMAT_YUV422, 121 DRM_FORMAT_YUV420, 122 }; 123 124 struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = { 125 .formats = rgb_and_yuv_formats, 126 .nformats = ARRAY_SIZE(rgb_and_yuv_formats), 127 }; 128 129 static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode) 130 { 131 switch (format) { 132 case DRM_FORMAT_C8: 133 *mode = ATMEL_HLCDC_C8_MODE; 134 break; 135 case DRM_FORMAT_XRGB4444: 136 *mode = ATMEL_HLCDC_XRGB4444_MODE; 137 break; 138 case DRM_FORMAT_ARGB4444: 139 *mode = ATMEL_HLCDC_ARGB4444_MODE; 140 break; 141 case DRM_FORMAT_RGBA4444: 142 *mode = ATMEL_HLCDC_RGBA4444_MODE; 143 break; 144 case DRM_FORMAT_RGB565: 145 *mode = ATMEL_HLCDC_RGB565_MODE; 146 break; 147 case DRM_FORMAT_RGB888: 148 *mode = ATMEL_HLCDC_RGB888_MODE; 149 break; 150 case DRM_FORMAT_ARGB1555: 151 *mode = ATMEL_HLCDC_ARGB1555_MODE; 152 break; 153 case DRM_FORMAT_XRGB8888: 154 *mode = ATMEL_HLCDC_XRGB8888_MODE; 155 break; 156 case DRM_FORMAT_ARGB8888: 157 *mode = ATMEL_HLCDC_ARGB8888_MODE; 158 break; 159 case DRM_FORMAT_RGBA8888: 160 *mode = ATMEL_HLCDC_RGBA8888_MODE; 161 break; 162 case DRM_FORMAT_AYUV: 163 *mode = ATMEL_HLCDC_AYUV_MODE; 164 break; 165 case DRM_FORMAT_YUYV: 166 *mode = ATMEL_HLCDC_YUYV_MODE; 167 break; 168 case DRM_FORMAT_UYVY: 169 *mode = ATMEL_HLCDC_UYVY_MODE; 170 break; 171 case DRM_FORMAT_YVYU: 172 *mode = ATMEL_HLCDC_YVYU_MODE; 173 break; 174 case DRM_FORMAT_VYUY: 175 *mode = ATMEL_HLCDC_VYUY_MODE; 176 break; 177 case DRM_FORMAT_NV21: 178 *mode = ATMEL_HLCDC_NV21_MODE; 179 break; 180 case DRM_FORMAT_NV61: 181 *mode = ATMEL_HLCDC_NV61_MODE; 182 break; 183 case DRM_FORMAT_YUV420: 184 *mode = ATMEL_HLCDC_YUV420_MODE; 185 break; 186 case DRM_FORMAT_YUV422: 187 *mode = ATMEL_HLCDC_YUV422_MODE; 188 break; 189 default: 190 return -ENOTSUPP; 191 } 192 193 return 0; 194 } 195 196 static u32 heo_downscaling_xcoef[] = { 197 0x11343311, 198 0x000000f7, 199 0x1635300c, 200 0x000000f9, 201 0x1b362c08, 202 0x000000fb, 203 0x1f372804, 204 0x000000fe, 205 0x24382400, 206 0x00000000, 207 0x28371ffe, 208 0x00000004, 209 0x2c361bfb, 210 0x00000008, 211 0x303516f9, 212 0x0000000c, 213 }; 214 215 static u32 heo_downscaling_ycoef[] = { 216 0x00123737, 217 0x00173732, 218 0x001b382d, 219 0x001f3928, 220 0x00243824, 221 0x0028391f, 222 0x002d381b, 223 0x00323717, 224 }; 225 226 static u32 heo_upscaling_xcoef[] = { 227 0xf74949f7, 228 0x00000000, 229 0xf55f33fb, 230 0x000000fe, 231 0xf5701efe, 232 0x000000ff, 233 0xf87c0dff, 234 0x00000000, 235 0x00800000, 236 0x00000000, 237 0x0d7cf800, 238 0x000000ff, 239 0x1e70f5ff, 240 0x000000fe, 241 0x335ff5fe, 242 0x000000fb, 243 }; 244 245 static u32 heo_upscaling_ycoef[] = { 246 0x00004040, 247 0x00075920, 248 0x00056f0c, 249 0x00027b03, 250 0x00008000, 251 0x00037b02, 252 0x000c6f05, 253 0x00205907, 254 }; 255 256 #define ATMEL_HLCDC_XPHIDEF 4 257 #define ATMEL_HLCDC_YPHIDEF 4 258 259 static u32 atmel_hlcdc_plane_phiscaler_get_factor(u32 srcsize, 260 u32 dstsize, 261 u32 phidef) 262 { 263 u32 factor, max_memsize; 264 265 factor = (256 * ((8 * (srcsize - 1)) - phidef)) / (dstsize - 1); 266 max_memsize = ((factor * (dstsize - 1)) + (256 * phidef)) / 2048; 267 268 if (max_memsize > srcsize - 1) 269 factor--; 270 271 return factor; 272 } 273 274 static void 275 atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane, 276 const u32 *coeff_tab, int size, 277 unsigned int cfg_offs) 278 { 279 int i; 280 281 for (i = 0; i < size; i++) 282 atmel_hlcdc_layer_write_cfg(&plane->layer, cfg_offs + i, 283 coeff_tab[i]); 284 } 285 286 static 287 void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, 288 struct atmel_hlcdc_plane_state *state) 289 { 290 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 291 u32 xfactor, yfactor; 292 293 if (!desc->layout.scaler_config) 294 return; 295 296 if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) { 297 atmel_hlcdc_layer_write_cfg(&plane->layer, 298 desc->layout.scaler_config, 0); 299 return; 300 } 301 302 if (desc->layout.phicoeffs.x) { 303 xfactor = atmel_hlcdc_plane_phiscaler_get_factor(state->src_w, 304 state->crtc_w, 305 ATMEL_HLCDC_XPHIDEF); 306 307 yfactor = atmel_hlcdc_plane_phiscaler_get_factor(state->src_h, 308 state->crtc_h, 309 ATMEL_HLCDC_YPHIDEF); 310 311 atmel_hlcdc_plane_scaler_set_phicoeff(plane, 312 state->crtc_w < state->src_w ? 313 heo_downscaling_xcoef : 314 heo_upscaling_xcoef, 315 ARRAY_SIZE(heo_upscaling_xcoef), 316 desc->layout.phicoeffs.x); 317 318 atmel_hlcdc_plane_scaler_set_phicoeff(plane, 319 state->crtc_h < state->src_h ? 320 heo_downscaling_ycoef : 321 heo_upscaling_ycoef, 322 ARRAY_SIZE(heo_upscaling_ycoef), 323 desc->layout.phicoeffs.y); 324 } else { 325 xfactor = (1024 * state->src_w) / state->crtc_w; 326 yfactor = (1024 * state->src_h) / state->crtc_h; 327 } 328 329 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config, 330 ATMEL_HLCDC_LAYER_SCALER_ENABLE | 331 ATMEL_HLCDC_LAYER_SCALER_FACTORS(xfactor, 332 yfactor)); 333 } 334 335 static 336 void atmel_xlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, 337 struct atmel_hlcdc_plane_state *state) 338 { 339 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 340 u32 xfactor, yfactor; 341 342 if (!desc->layout.scaler_config) 343 return; 344 345 if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) { 346 atmel_hlcdc_layer_write_cfg(&plane->layer, 347 desc->layout.scaler_config, 0); 348 return; 349 } 350 351 /* xfactor = round[(2^20 * XMEMSIZE)/XSIZE)] */ 352 xfactor = (u32)(((1 << 20) * state->src_w) / state->crtc_w); 353 354 /* yfactor = round[(2^20 * YMEMSIZE)/YSIZE)] */ 355 yfactor = (u32)(((1 << 20) * state->src_h) / state->crtc_h); 356 357 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config, 358 ATMEL_XLCDC_LAYER_VSCALER_LUMA_ENABLE | 359 ATMEL_XLCDC_LAYER_VSCALER_CHROMA_ENABLE | 360 ATMEL_XLCDC_LAYER_HSCALER_LUMA_ENABLE | 361 ATMEL_XLCDC_LAYER_HSCALER_CHROMA_ENABLE); 362 363 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 1, 364 yfactor); 365 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 3, 366 xfactor); 367 368 /* 369 * With YCbCr 4:2:0 window resampling, configuration register 370 * LCDC_HEOCFG25.VXSCFACT and LCDC_HEOCFG27.HXSCFACT values are half 371 * the value of yfactor and xfactor. 372 * 373 * On the other hand, with YCbCr 4:2:2 window resampling, only the 374 * configuration register LCDC_HEOCFG27.HXSCFACT value is half the value 375 * of the xfactor; the value of LCDC_HEOCFG25.VXSCFACT is yfactor (no 376 * division by 2). 377 */ 378 switch (state->base.fb->format->format) { 379 /* YCbCr 4:2:2 */ 380 case DRM_FORMAT_YUYV: 381 case DRM_FORMAT_UYVY: 382 case DRM_FORMAT_YVYU: 383 case DRM_FORMAT_VYUY: 384 case DRM_FORMAT_YUV422: 385 case DRM_FORMAT_NV61: 386 xfactor /= 2; 387 break; 388 389 /* YCbCr 4:2:0 */ 390 case DRM_FORMAT_YUV420: 391 case DRM_FORMAT_NV21: 392 yfactor /= 2; 393 xfactor /= 2; 394 break; 395 default: 396 break; 397 } 398 399 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 2, 400 yfactor); 401 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 4, 402 xfactor); 403 } 404 405 static void 406 atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, 407 struct atmel_hlcdc_plane_state *state) 408 { 409 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 410 struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 411 412 if (desc->layout.size) 413 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size, 414 ATMEL_HLCDC_LAYER_SIZE(state->crtc_w, 415 state->crtc_h)); 416 417 if (desc->layout.memsize) 418 atmel_hlcdc_layer_write_cfg(&plane->layer, 419 desc->layout.memsize, 420 ATMEL_HLCDC_LAYER_SIZE(state->src_w, 421 state->src_h)); 422 423 if (desc->layout.pos) 424 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.pos, 425 ATMEL_HLCDC_LAYER_POS(state->crtc_x, 426 state->crtc_y)); 427 428 dc->desc->ops->plane_setup_scaler(plane, state); 429 } 430 431 static 432 void atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, 433 struct atmel_hlcdc_plane_state *state) 434 { 435 unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id; 436 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 437 const struct drm_format_info *format = state->base.fb->format; 438 439 /* 440 * Rotation optimization is not working on RGB888 (rotation is still 441 * working but without any optimization). 442 */ 443 if (format->format == DRM_FORMAT_RGB888) 444 cfg |= ATMEL_HLCDC_LAYER_DMA_ROTDIS; 445 446 atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG, 447 cfg); 448 449 cfg = ATMEL_HLCDC_LAYER_DMA | ATMEL_HLCDC_LAYER_REP; 450 451 if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) { 452 cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL | 453 ATMEL_HLCDC_LAYER_ITER; 454 455 if (format->has_alpha) 456 cfg |= ATMEL_HLCDC_LAYER_LAEN; 457 else 458 cfg |= ATMEL_HLCDC_LAYER_GAEN | 459 ATMEL_HLCDC_LAYER_GA(state->base.alpha); 460 } 461 462 if (state->disc_h && state->disc_w) 463 cfg |= ATMEL_HLCDC_LAYER_DISCEN; 464 465 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config, 466 cfg); 467 } 468 469 static 470 void atmel_xlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, 471 struct atmel_hlcdc_plane_state *state) 472 { 473 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 474 const struct drm_format_info *format = state->base.fb->format; 475 unsigned int cfg; 476 477 atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_XLCDC_LAYER_DMA_CFG, 478 ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id); 479 480 cfg = ATMEL_XLCDC_LAYER_DMA | ATMEL_XLCDC_LAYER_REP; 481 482 if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) { 483 /* 484 * Alpha Blending bits specific to SAM9X7 SoC 485 */ 486 cfg |= ATMEL_XLCDC_LAYER_SFACTC_A0_MULT_AS | 487 ATMEL_XLCDC_LAYER_SFACTA_ONE | 488 ATMEL_XLCDC_LAYER_DFACTC_M_A0_MULT_AS | 489 ATMEL_XLCDC_LAYER_DFACTA_ONE; 490 if (format->has_alpha) 491 cfg |= ATMEL_XLCDC_LAYER_A0(0xff); 492 else 493 cfg |= ATMEL_XLCDC_LAYER_A0(state->base.alpha); 494 } 495 496 if (state->disc_h && state->disc_w) 497 cfg |= ATMEL_XLCDC_LAYER_DISCEN; 498 499 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config, 500 cfg); 501 } 502 503 static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, 504 struct atmel_hlcdc_plane_state *state) 505 { 506 u32 cfg; 507 int ret; 508 509 ret = atmel_hlcdc_format_to_plane_mode(state->base.fb->format->format, 510 &cfg); 511 if (ret) 512 return; 513 514 if ((state->base.fb->format->format == DRM_FORMAT_YUV422 || 515 state->base.fb->format->format == DRM_FORMAT_NV61) && 516 drm_rotation_90_or_270(state->base.rotation)) 517 cfg |= ATMEL_HLCDC_YUV422ROT; 518 519 atmel_hlcdc_layer_write_cfg(&plane->layer, 520 ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg); 521 } 522 523 static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane, 524 struct atmel_hlcdc_plane_state *state) 525 { 526 struct drm_crtc *crtc = state->base.crtc; 527 struct drm_color_lut *lut; 528 int idx; 529 530 if (!crtc || !crtc->state) 531 return; 532 533 if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut) 534 return; 535 536 lut = (struct drm_color_lut *)crtc->state->gamma_lut->data; 537 538 for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) { 539 u32 val = ((lut->red << 8) & 0xff0000) | 540 (lut->green & 0xff00) | 541 (lut->blue >> 8); 542 543 atmel_hlcdc_layer_write_clut(&plane->layer, idx, val); 544 } 545 } 546 547 static void atmel_hlcdc_update_buffers(struct atmel_hlcdc_plane *plane, 548 struct atmel_hlcdc_plane_state *state, 549 u32 sr, int i) 550 { 551 atmel_hlcdc_layer_write_reg(&plane->layer, 552 ATMEL_HLCDC_LAYER_PLANE_HEAD(i), 553 state->dscrs[i]->self); 554 555 if (sr & ATMEL_HLCDC_LAYER_EN) 556 return; 557 558 atmel_hlcdc_layer_write_reg(&plane->layer, 559 ATMEL_HLCDC_LAYER_PLANE_ADDR(i), 560 state->dscrs[i]->addr); 561 atmel_hlcdc_layer_write_reg(&plane->layer, 562 ATMEL_HLCDC_LAYER_PLANE_CTRL(i), 563 state->dscrs[i]->ctrl); 564 atmel_hlcdc_layer_write_reg(&plane->layer, 565 ATMEL_HLCDC_LAYER_PLANE_NEXT(i), 566 state->dscrs[i]->self); 567 } 568 569 static void atmel_xlcdc_update_buffers(struct atmel_hlcdc_plane *plane, 570 struct atmel_hlcdc_plane_state *state, 571 u32 sr, int i) 572 { 573 atmel_hlcdc_layer_write_reg(&plane->layer, 574 ATMEL_XLCDC_LAYER_PLANE_ADDR(i), 575 state->dscrs[i]->addr); 576 } 577 578 static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, 579 struct atmel_hlcdc_plane_state *state) 580 { 581 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 582 struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 583 struct drm_framebuffer *fb = state->base.fb; 584 u32 sr; 585 int i; 586 587 if (!dc->desc->is_xlcdc) 588 sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); 589 590 for (i = 0; i < state->nplanes; i++) { 591 struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); 592 593 state->dscrs[i]->addr = gem->dma_addr + state->offsets[i]; 594 595 dc->desc->ops->lcdc_update_buffers(plane, state, sr, i); 596 597 if (desc->layout.xstride[i]) 598 atmel_hlcdc_layer_write_cfg(&plane->layer, 599 desc->layout.xstride[i], 600 state->xstride[i]); 601 602 if (desc->layout.pstride[i]) 603 atmel_hlcdc_layer_write_cfg(&plane->layer, 604 desc->layout.pstride[i], 605 state->pstride[i]); 606 } 607 } 608 609 int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state) 610 { 611 unsigned int ahb_load[2] = { }; 612 struct drm_plane *plane; 613 614 drm_atomic_crtc_state_for_each_plane(plane, c_state) { 615 struct atmel_hlcdc_plane_state *plane_state; 616 struct drm_plane_state *plane_s; 617 unsigned int pixels, load = 0; 618 int i; 619 620 plane_s = drm_atomic_get_plane_state(c_state->state, plane); 621 if (IS_ERR(plane_s)) 622 return PTR_ERR(plane_s); 623 624 plane_state = 625 drm_plane_state_to_atmel_hlcdc_plane_state(plane_s); 626 627 pixels = (plane_state->src_w * plane_state->src_h) - 628 (plane_state->disc_w * plane_state->disc_h); 629 630 for (i = 0; i < plane_state->nplanes; i++) 631 load += pixels * plane_state->bpp[i]; 632 633 if (ahb_load[0] <= ahb_load[1]) 634 plane_state->ahb_id = 0; 635 else 636 plane_state->ahb_id = 1; 637 638 ahb_load[plane_state->ahb_id] += load; 639 } 640 641 return 0; 642 } 643 644 int 645 atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state) 646 { 647 int disc_x = 0, disc_y = 0, disc_w = 0, disc_h = 0; 648 const struct atmel_hlcdc_layer_cfg_layout *layout; 649 struct atmel_hlcdc_plane_state *primary_state; 650 struct drm_plane_state *primary_s; 651 struct atmel_hlcdc_plane *primary; 652 struct drm_plane *ovl; 653 654 primary = drm_plane_to_atmel_hlcdc_plane(c_state->crtc->primary); 655 layout = &primary->layer.desc->layout; 656 if (!layout->disc_pos || !layout->disc_size) 657 return 0; 658 659 primary_s = drm_atomic_get_plane_state(c_state->state, 660 &primary->base); 661 if (IS_ERR(primary_s)) 662 return PTR_ERR(primary_s); 663 664 primary_state = drm_plane_state_to_atmel_hlcdc_plane_state(primary_s); 665 666 drm_atomic_crtc_state_for_each_plane(ovl, c_state) { 667 struct atmel_hlcdc_plane_state *ovl_state; 668 struct drm_plane_state *ovl_s; 669 670 if (ovl == c_state->crtc->primary) 671 continue; 672 673 ovl_s = drm_atomic_get_plane_state(c_state->state, ovl); 674 if (IS_ERR(ovl_s)) 675 return PTR_ERR(ovl_s); 676 677 ovl_state = drm_plane_state_to_atmel_hlcdc_plane_state(ovl_s); 678 679 if (!ovl_s->visible || 680 !ovl_s->fb || 681 ovl_s->fb->format->has_alpha || 682 ovl_s->alpha != DRM_BLEND_ALPHA_OPAQUE) 683 continue; 684 685 /* TODO: implement a smarter hidden area detection */ 686 if (ovl_state->crtc_h * ovl_state->crtc_w < disc_h * disc_w) 687 continue; 688 689 disc_x = ovl_state->crtc_x; 690 disc_y = ovl_state->crtc_y; 691 disc_h = ovl_state->crtc_h; 692 disc_w = ovl_state->crtc_w; 693 } 694 695 primary_state->disc_x = disc_x; 696 primary_state->disc_y = disc_y; 697 primary_state->disc_w = disc_w; 698 primary_state->disc_h = disc_h; 699 700 return 0; 701 } 702 703 static void 704 atmel_hlcdc_plane_update_disc_area(struct atmel_hlcdc_plane *plane, 705 struct atmel_hlcdc_plane_state *state) 706 { 707 const struct atmel_hlcdc_layer_cfg_layout *layout; 708 709 layout = &plane->layer.desc->layout; 710 if (!layout->disc_pos || !layout->disc_size) 711 return; 712 713 atmel_hlcdc_layer_write_cfg(&plane->layer, layout->disc_pos, 714 ATMEL_HLCDC_LAYER_DISC_POS(state->disc_x, 715 state->disc_y)); 716 717 atmel_hlcdc_layer_write_cfg(&plane->layer, layout->disc_size, 718 ATMEL_HLCDC_LAYER_DISC_SIZE(state->disc_w, 719 state->disc_h)); 720 } 721 722 static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, 723 struct drm_atomic_state *state) 724 { 725 struct drm_plane_state *s = drm_atomic_get_new_plane_state(state, p); 726 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 727 struct atmel_hlcdc_plane_state *hstate = 728 drm_plane_state_to_atmel_hlcdc_plane_state(s); 729 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 730 struct drm_framebuffer *fb = hstate->base.fb; 731 const struct drm_display_mode *mode; 732 struct drm_crtc_state *crtc_state; 733 int ret; 734 int i; 735 736 if (!hstate->base.crtc || WARN_ON(!fb)) 737 return 0; 738 739 crtc_state = drm_atomic_get_new_crtc_state(state, s->crtc); 740 mode = &crtc_state->adjusted_mode; 741 742 ret = drm_atomic_helper_check_plane_state(s, crtc_state, 743 (1 << 16) / 2048, 744 INT_MAX, true, true); 745 if (ret || !s->visible) 746 return ret; 747 748 hstate->src_x = s->src.x1; 749 hstate->src_y = s->src.y1; 750 hstate->src_w = drm_rect_width(&s->src); 751 hstate->src_h = drm_rect_height(&s->src); 752 hstate->crtc_x = s->dst.x1; 753 hstate->crtc_y = s->dst.y1; 754 hstate->crtc_w = drm_rect_width(&s->dst); 755 hstate->crtc_h = drm_rect_height(&s->dst); 756 757 if ((hstate->src_x | hstate->src_y | hstate->src_w | hstate->src_h) & 758 SUBPIXEL_MASK) 759 return -EINVAL; 760 761 hstate->src_x >>= 16; 762 hstate->src_y >>= 16; 763 hstate->src_w >>= 16; 764 hstate->src_h >>= 16; 765 766 hstate->nplanes = fb->format->num_planes; 767 if (hstate->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES) 768 return -EINVAL; 769 770 for (i = 0; i < hstate->nplanes; i++) { 771 unsigned int offset = 0; 772 int xdiv = i ? fb->format->hsub : 1; 773 int ydiv = i ? fb->format->vsub : 1; 774 775 hstate->bpp[i] = fb->format->cpp[i]; 776 if (!hstate->bpp[i]) 777 return -EINVAL; 778 779 switch (hstate->base.rotation & DRM_MODE_ROTATE_MASK) { 780 case DRM_MODE_ROTATE_90: 781 offset = (hstate->src_y / ydiv) * 782 fb->pitches[i]; 783 offset += ((hstate->src_x + hstate->src_w - 1) / 784 xdiv) * hstate->bpp[i]; 785 hstate->xstride[i] = -(((hstate->src_h - 1) / ydiv) * 786 fb->pitches[i]) - 787 (2 * hstate->bpp[i]); 788 hstate->pstride[i] = fb->pitches[i] - hstate->bpp[i]; 789 break; 790 case DRM_MODE_ROTATE_180: 791 offset = ((hstate->src_y + hstate->src_h - 1) / 792 ydiv) * fb->pitches[i]; 793 offset += ((hstate->src_x + hstate->src_w - 1) / 794 xdiv) * hstate->bpp[i]; 795 hstate->xstride[i] = ((((hstate->src_w - 1) / xdiv) - 1) * 796 hstate->bpp[i]) - fb->pitches[i]; 797 hstate->pstride[i] = -2 * hstate->bpp[i]; 798 break; 799 case DRM_MODE_ROTATE_270: 800 offset = ((hstate->src_y + hstate->src_h - 1) / 801 ydiv) * fb->pitches[i]; 802 offset += (hstate->src_x / xdiv) * hstate->bpp[i]; 803 hstate->xstride[i] = ((hstate->src_h - 1) / ydiv) * 804 fb->pitches[i]; 805 hstate->pstride[i] = -fb->pitches[i] - hstate->bpp[i]; 806 break; 807 case DRM_MODE_ROTATE_0: 808 default: 809 offset = (hstate->src_y / ydiv) * fb->pitches[i]; 810 offset += (hstate->src_x / xdiv) * hstate->bpp[i]; 811 hstate->xstride[i] = fb->pitches[i] - 812 ((hstate->src_w / xdiv) * 813 hstate->bpp[i]); 814 hstate->pstride[i] = 0; 815 break; 816 } 817 818 hstate->offsets[i] = offset + fb->offsets[i]; 819 } 820 821 /* 822 * Swap width and size in case of 90 or 270 degrees rotation 823 */ 824 if (drm_rotation_90_or_270(hstate->base.rotation)) { 825 swap(hstate->src_w, hstate->src_h); 826 } 827 828 if (!desc->layout.size && 829 (mode->hdisplay != hstate->crtc_w || 830 mode->vdisplay != hstate->crtc_h)) 831 return -EINVAL; 832 833 if ((hstate->crtc_h != hstate->src_h || hstate->crtc_w != hstate->src_w) && 834 (!desc->layout.memsize || 835 hstate->base.fb->format->has_alpha)) 836 return -EINVAL; 837 838 return 0; 839 } 840 841 static void atmel_hlcdc_atomic_disable(struct atmel_hlcdc_plane *plane, 842 struct atmel_hlcdc_dc *dc) 843 { 844 /* Disable interrupts */ 845 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR, 846 0xffffffff); 847 848 /* Disable the layer */ 849 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHDR, 850 ATMEL_HLCDC_LAYER_RST | 851 ATMEL_HLCDC_LAYER_A2Q | 852 ATMEL_HLCDC_LAYER_UPDATE); 853 854 /* Clear all pending interrupts */ 855 atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); 856 } 857 858 static void atmel_xlcdc_atomic_disable(struct atmel_hlcdc_plane *plane, 859 struct atmel_hlcdc_dc *dc) 860 { 861 /* Disable interrupts */ 862 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IDR, 863 0xffffffff); 864 865 /* Disable the layer */ 866 atmel_hlcdc_layer_write_reg(&plane->layer, 867 ATMEL_XLCDC_LAYER_ENR, 0); 868 869 /* 870 * Updating XLCDC_xxxCFGx, XLCDC_xxxFBA and XLCDC_xxxEN, 871 * (where xxx indicates each layer) requires writing one to the 872 * Update Attribute field for each layer in LCDC_ATTRE register for SAM9X7. 873 */ 874 regmap_write(dc->hlcdc->regmap, ATMEL_XLCDC_ATTRE, ATMEL_XLCDC_BASE_UPDATE | 875 ATMEL_XLCDC_OVR1_UPDATE | ATMEL_XLCDC_OVR3_UPDATE | 876 ATMEL_XLCDC_HEO_UPDATE); 877 878 /* Clear all pending interrupts */ 879 atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR); 880 } 881 882 static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, 883 struct drm_atomic_state *state) 884 { 885 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 886 struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 887 888 dc->desc->ops->lcdc_atomic_disable(plane, dc); 889 } 890 891 static void atmel_hlcdc_atomic_update(struct atmel_hlcdc_plane *plane, 892 struct atmel_hlcdc_dc *dc) 893 { 894 u32 sr; 895 896 /* Enable the overrun interrupts. */ 897 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER, 898 ATMEL_HLCDC_LAYER_OVR_IRQ(0) | 899 ATMEL_HLCDC_LAYER_OVR_IRQ(1) | 900 ATMEL_HLCDC_LAYER_OVR_IRQ(2)); 901 902 /* Apply the new config at the next SOF event. */ 903 sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); 904 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER, 905 ATMEL_HLCDC_LAYER_UPDATE | 906 (sr & ATMEL_HLCDC_LAYER_EN ? 907 ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); 908 } 909 910 static void atmel_xlcdc_atomic_update(struct atmel_hlcdc_plane *plane, 911 struct atmel_hlcdc_dc *dc) 912 { 913 /* Enable the overrun interrupts. */ 914 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IER, 915 ATMEL_XLCDC_LAYER_OVR_IRQ(0) | 916 ATMEL_XLCDC_LAYER_OVR_IRQ(1) | 917 ATMEL_XLCDC_LAYER_OVR_IRQ(2)); 918 919 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_ENR, 920 ATMEL_XLCDC_LAYER_EN); 921 922 /* 923 * Updating XLCDC_xxxCFGx, XLCDC_xxxFBA and XLCDC_xxxEN, 924 * (where xxx indicates each layer) requires writing one to the 925 * Update Attribute field for each layer in LCDC_ATTRE register for SAM9X7. 926 */ 927 regmap_write(dc->hlcdc->regmap, ATMEL_XLCDC_ATTRE, ATMEL_XLCDC_BASE_UPDATE | 928 ATMEL_XLCDC_OVR1_UPDATE | ATMEL_XLCDC_OVR3_UPDATE | 929 ATMEL_XLCDC_HEO_UPDATE); 930 } 931 932 static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, 933 struct drm_atomic_state *state) 934 { 935 struct drm_plane_state *new_s = drm_atomic_get_new_plane_state(state, 936 p); 937 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 938 struct atmel_hlcdc_plane_state *hstate = 939 drm_plane_state_to_atmel_hlcdc_plane_state(new_s); 940 struct atmel_hlcdc_dc *dc = p->dev->dev_private; 941 942 if (!new_s->crtc || !new_s->fb) 943 return; 944 945 if (!hstate->base.visible) { 946 atmel_hlcdc_plane_atomic_disable(p, state); 947 return; 948 } 949 950 atmel_hlcdc_plane_update_pos_and_size(plane, hstate); 951 dc->desc->ops->lcdc_update_general_settings(plane, hstate); 952 atmel_hlcdc_plane_update_format(plane, hstate); 953 atmel_hlcdc_plane_update_clut(plane, hstate); 954 atmel_hlcdc_plane_update_buffers(plane, hstate); 955 atmel_hlcdc_plane_update_disc_area(plane, hstate); 956 957 dc->desc->ops->lcdc_atomic_update(plane, dc); 958 } 959 960 static void atmel_hlcdc_csc_init(struct atmel_hlcdc_plane *plane, 961 const struct atmel_hlcdc_layer_desc *desc) 962 { 963 /* 964 * TODO: declare a "yuv-to-rgb-conv-factors" property to let 965 * userspace modify these factors (using a BLOB property ?). 966 */ 967 static const u32 hlcdc_csc_coeffs[] = { 968 0x4c900091, 969 0x7a5f5090, 970 0x40040890 971 }; 972 973 for (int i = 0; i < ARRAY_SIZE(hlcdc_csc_coeffs); i++) { 974 atmel_hlcdc_layer_write_cfg(&plane->layer, 975 desc->layout.csc + i, 976 hlcdc_csc_coeffs[i]); 977 } 978 } 979 980 static void atmel_xlcdc_csc_init(struct atmel_hlcdc_plane *plane, 981 const struct atmel_hlcdc_layer_desc *desc) 982 { 983 /* 984 * yuv-to-rgb-conv-factors are now defined from LCDC_HEOCFG16 to 985 * LCDC_HEOCFG21 registers in SAM9X7. 986 */ 987 static const u32 xlcdc_csc_coeffs[] = { 988 0x00000488, 989 0x00000648, 990 0x1EA00480, 991 0x00001D28, 992 0x08100480, 993 0x00000000, 994 0x00000007 995 }; 996 997 for (int i = 0; i < ARRAY_SIZE(xlcdc_csc_coeffs); i++) { 998 atmel_hlcdc_layer_write_cfg(&plane->layer, 999 desc->layout.csc + i, 1000 xlcdc_csc_coeffs[i]); 1001 } 1002 1003 if (desc->layout.vxs_config && desc->layout.hxs_config) { 1004 /* 1005 * Updating vxs.config and hxs.config fixes the 1006 * Green Color Issue in SAM9X7 EGT Video Player App 1007 */ 1008 atmel_hlcdc_layer_write_cfg(&plane->layer, 1009 desc->layout.vxs_config, 1010 ATMEL_XLCDC_LAYER_VXSYCFG_ONE | 1011 ATMEL_XLCDC_LAYER_VXSYTAP2_ENABLE | 1012 ATMEL_XLCDC_LAYER_VXSCCFG_ONE | 1013 ATMEL_XLCDC_LAYER_VXSCTAP2_ENABLE); 1014 1015 atmel_hlcdc_layer_write_cfg(&plane->layer, 1016 desc->layout.hxs_config, 1017 ATMEL_XLCDC_LAYER_HXSYCFG_ONE | 1018 ATMEL_XLCDC_LAYER_HXSYTAP2_ENABLE | 1019 ATMEL_XLCDC_LAYER_HXSCCFG_ONE | 1020 ATMEL_XLCDC_LAYER_HXSCTAP2_ENABLE); 1021 } 1022 } 1023 1024 static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane) 1025 { 1026 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 1027 struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 1028 1029 if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER || 1030 desc->type == ATMEL_HLCDC_CURSOR_LAYER) { 1031 int ret; 1032 1033 ret = drm_plane_create_alpha_property(&plane->base); 1034 if (ret) 1035 return ret; 1036 } 1037 1038 if (desc->layout.xstride[0] && desc->layout.pstride[0]) { 1039 int ret; 1040 1041 ret = drm_plane_create_rotation_property(&plane->base, 1042 DRM_MODE_ROTATE_0, 1043 DRM_MODE_ROTATE_0 | 1044 DRM_MODE_ROTATE_90 | 1045 DRM_MODE_ROTATE_180 | 1046 DRM_MODE_ROTATE_270); 1047 if (ret) 1048 return ret; 1049 } 1050 1051 if (desc->layout.csc) 1052 dc->desc->ops->lcdc_csc_init(plane, desc); 1053 1054 return 0; 1055 } 1056 1057 static void atmel_hlcdc_irq_dbg(struct atmel_hlcdc_plane *plane, 1058 const struct atmel_hlcdc_layer_desc *desc) 1059 { 1060 u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); 1061 1062 /* 1063 * There's not much we can do in case of overrun except informing 1064 * the user. However, we are in interrupt context here, hence the 1065 * use of dev_dbg(). 1066 */ 1067 if (isr & 1068 (ATMEL_HLCDC_LAYER_OVR_IRQ(0) | ATMEL_HLCDC_LAYER_OVR_IRQ(1) | 1069 ATMEL_HLCDC_LAYER_OVR_IRQ(2))) 1070 drm_dbg(plane->base.dev, "overrun on plane %s\n", 1071 desc->name); 1072 } 1073 1074 static void atmel_xlcdc_irq_dbg(struct atmel_hlcdc_plane *plane, 1075 const struct atmel_hlcdc_layer_desc *desc) 1076 { 1077 u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR); 1078 1079 /* 1080 * There's not much we can do in case of overrun except informing 1081 * the user. However, we are in interrupt context here, hence the 1082 * use of dev_dbg(). 1083 */ 1084 if (isr & 1085 (ATMEL_XLCDC_LAYER_OVR_IRQ(0) | ATMEL_XLCDC_LAYER_OVR_IRQ(1) | 1086 ATMEL_XLCDC_LAYER_OVR_IRQ(2))) 1087 drm_dbg(plane->base.dev, "overrun on plane %s\n", 1088 desc->name); 1089 } 1090 1091 void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) 1092 { 1093 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 1094 struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 1095 1096 dc->desc->ops->lcdc_irq_dbg(plane, desc); 1097 } 1098 1099 const struct atmel_lcdc_dc_ops atmel_hlcdc_ops = { 1100 .plane_setup_scaler = atmel_hlcdc_plane_setup_scaler, 1101 .lcdc_update_buffers = atmel_hlcdc_update_buffers, 1102 .lcdc_atomic_disable = atmel_hlcdc_atomic_disable, 1103 .lcdc_update_general_settings = atmel_hlcdc_plane_update_general_settings, 1104 .lcdc_atomic_update = atmel_hlcdc_atomic_update, 1105 .lcdc_csc_init = atmel_hlcdc_csc_init, 1106 .lcdc_irq_dbg = atmel_hlcdc_irq_dbg, 1107 }; 1108 1109 const struct atmel_lcdc_dc_ops atmel_xlcdc_ops = { 1110 .plane_setup_scaler = atmel_xlcdc_plane_setup_scaler, 1111 .lcdc_update_buffers = atmel_xlcdc_update_buffers, 1112 .lcdc_atomic_disable = atmel_xlcdc_atomic_disable, 1113 .lcdc_update_general_settings = atmel_xlcdc_plane_update_general_settings, 1114 .lcdc_atomic_update = atmel_xlcdc_atomic_update, 1115 .lcdc_csc_init = atmel_xlcdc_csc_init, 1116 .lcdc_irq_dbg = atmel_xlcdc_irq_dbg, 1117 }; 1118 1119 static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { 1120 .atomic_check = atmel_hlcdc_plane_atomic_check, 1121 .atomic_update = atmel_hlcdc_plane_atomic_update, 1122 .atomic_disable = atmel_hlcdc_plane_atomic_disable, 1123 }; 1124 1125 static int atmel_hlcdc_plane_alloc_dscrs(struct drm_plane *p, 1126 struct atmel_hlcdc_plane_state *state) 1127 { 1128 struct atmel_hlcdc_dc *dc = p->dev->dev_private; 1129 int i; 1130 1131 for (i = 0; i < ARRAY_SIZE(state->dscrs); i++) { 1132 struct atmel_hlcdc_dma_channel_dscr *dscr; 1133 dma_addr_t dscr_dma; 1134 1135 dscr = dma_pool_alloc(dc->dscrpool, GFP_KERNEL, &dscr_dma); 1136 if (!dscr) 1137 goto err; 1138 1139 dscr->addr = 0; 1140 dscr->next = dscr_dma; 1141 dscr->self = dscr_dma; 1142 dscr->ctrl = ATMEL_HLCDC_LAYER_DFETCH; 1143 1144 state->dscrs[i] = dscr; 1145 } 1146 1147 return 0; 1148 1149 err: 1150 for (i--; i >= 0; i--) { 1151 dma_pool_free(dc->dscrpool, state->dscrs[i], 1152 state->dscrs[i]->self); 1153 } 1154 1155 return -ENOMEM; 1156 } 1157 1158 static void atmel_hlcdc_plane_reset(struct drm_plane *p) 1159 { 1160 struct atmel_hlcdc_plane_state *state; 1161 1162 if (p->state) { 1163 state = drm_plane_state_to_atmel_hlcdc_plane_state(p->state); 1164 1165 if (state->base.fb) 1166 drm_framebuffer_put(state->base.fb); 1167 1168 kfree(state); 1169 p->state = NULL; 1170 } 1171 1172 state = kzalloc(sizeof(*state), GFP_KERNEL); 1173 if (state) { 1174 if (atmel_hlcdc_plane_alloc_dscrs(p, state)) { 1175 kfree(state); 1176 drm_err(p->dev, 1177 "Failed to allocate initial plane state\n"); 1178 return; 1179 } 1180 __drm_atomic_helper_plane_reset(p, &state->base); 1181 } 1182 } 1183 1184 static struct drm_plane_state * 1185 atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p) 1186 { 1187 struct atmel_hlcdc_plane_state *state = 1188 drm_plane_state_to_atmel_hlcdc_plane_state(p->state); 1189 struct atmel_hlcdc_plane_state *copy; 1190 1191 copy = kmemdup(state, sizeof(*state), GFP_KERNEL); 1192 if (!copy) 1193 return NULL; 1194 1195 if (atmel_hlcdc_plane_alloc_dscrs(p, copy)) { 1196 kfree(copy); 1197 return NULL; 1198 } 1199 1200 if (copy->base.fb) 1201 drm_framebuffer_get(copy->base.fb); 1202 1203 return ©->base; 1204 } 1205 1206 static void atmel_hlcdc_plane_atomic_destroy_state(struct drm_plane *p, 1207 struct drm_plane_state *s) 1208 { 1209 struct atmel_hlcdc_plane_state *state = 1210 drm_plane_state_to_atmel_hlcdc_plane_state(s); 1211 struct atmel_hlcdc_dc *dc = p->dev->dev_private; 1212 int i; 1213 1214 for (i = 0; i < ARRAY_SIZE(state->dscrs); i++) { 1215 dma_pool_free(dc->dscrpool, state->dscrs[i], 1216 state->dscrs[i]->self); 1217 } 1218 1219 if (s->fb) 1220 drm_framebuffer_put(s->fb); 1221 1222 kfree(state); 1223 } 1224 1225 static const struct drm_plane_funcs layer_plane_funcs = { 1226 .update_plane = drm_atomic_helper_update_plane, 1227 .disable_plane = drm_atomic_helper_disable_plane, 1228 .destroy = drm_plane_cleanup, 1229 .reset = atmel_hlcdc_plane_reset, 1230 .atomic_duplicate_state = atmel_hlcdc_plane_atomic_duplicate_state, 1231 .atomic_destroy_state = atmel_hlcdc_plane_atomic_destroy_state, 1232 }; 1233 1234 static int atmel_hlcdc_plane_create(struct drm_device *dev, 1235 const struct atmel_hlcdc_layer_desc *desc) 1236 { 1237 struct atmel_hlcdc_dc *dc = dev->dev_private; 1238 struct atmel_hlcdc_plane *plane; 1239 enum drm_plane_type type; 1240 int ret; 1241 1242 plane = devm_kzalloc(dev->dev, sizeof(*plane), GFP_KERNEL); 1243 if (!plane) 1244 return -ENOMEM; 1245 1246 atmel_hlcdc_layer_init(&plane->layer, desc, dc->hlcdc->regmap); 1247 1248 if (desc->type == ATMEL_HLCDC_BASE_LAYER) 1249 type = DRM_PLANE_TYPE_PRIMARY; 1250 else if (desc->type == ATMEL_HLCDC_CURSOR_LAYER) 1251 type = DRM_PLANE_TYPE_CURSOR; 1252 else 1253 type = DRM_PLANE_TYPE_OVERLAY; 1254 1255 ret = drm_universal_plane_init(dev, &plane->base, 0, 1256 &layer_plane_funcs, 1257 desc->formats->formats, 1258 desc->formats->nformats, 1259 NULL, type, NULL); 1260 if (ret) 1261 return ret; 1262 1263 drm_plane_helper_add(&plane->base, 1264 &atmel_hlcdc_layer_plane_helper_funcs); 1265 1266 /* Set default property values*/ 1267 ret = atmel_hlcdc_plane_init_properties(plane); 1268 if (ret) 1269 return ret; 1270 1271 dc->layers[desc->id] = &plane->layer; 1272 1273 return 0; 1274 } 1275 1276 int atmel_hlcdc_create_planes(struct drm_device *dev) 1277 { 1278 struct atmel_hlcdc_dc *dc = dev->dev_private; 1279 const struct atmel_hlcdc_layer_desc *descs = dc->desc->layers; 1280 int nlayers = dc->desc->nlayers; 1281 int i, ret; 1282 1283 dc->dscrpool = dmam_pool_create("atmel-hlcdc-dscr", dev->dev, 1284 sizeof(struct atmel_hlcdc_dma_channel_dscr), 1285 sizeof(u64), 0); 1286 if (!dc->dscrpool) 1287 return -ENOMEM; 1288 1289 for (i = 0; i < nlayers; i++) { 1290 if (descs[i].type != ATMEL_HLCDC_BASE_LAYER && 1291 descs[i].type != ATMEL_HLCDC_OVERLAY_LAYER && 1292 descs[i].type != ATMEL_HLCDC_CURSOR_LAYER) 1293 continue; 1294 1295 ret = atmel_hlcdc_plane_create(dev, &descs[i]); 1296 if (ret) 1297 return ret; 1298 } 1299 1300 return 0; 1301 } 1302