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

Merge tag 'imx-drm-next-2016-11-10' of git://git.pengutronix.de/git/pza/linux into drm-next

imx-drm plane update cleanup, YUV formats

- request modeset if plane offsets changed, only the plane base
address can be changed without disabling the plane IDMAC channel.
- cleanup of plane atomic_update
- remove unused ipu_cpmem_set_yuv_planar function
- support YUV 4:4:4, 4:2:2, NV12 and NV16 plane formats
- not only mask interrupts during irq init, also clear them
- remove a legacy check from imx-ldb
- add support to set the CSI downsizing bits
- silence an obnoxious warning during modeset

* tag 'imx-drm-next-2016-11-10' of git://git.pengutronix.de/git/pza/linux:
gpu: ipu-di: silence videomode logspam
gpu: ipu-v3: add ipu_csi_set_downsize
drm/imx: imx-ldb: remove unnecessary double disable check
gpu: ipu-v3: initially clear all interrupts
drm/imx: ipuv3-plane: add support for YUV 4:2:2 and 4:4:4, NV12, and NV16 formats
gpu: ipu-v3: add YUV 4:4:4 support
gpu: ipu-cpmem: remove unused ipu_cpmem_set_yuv_planar function
drm/imx: ipuv3-plane: let drm_plane_state_to_ubo/vbo handle chroma subsampling other than 4:2:0
drm/imx: ipuv3-plane: merge ipu_plane_atomic_set_base into atomic_update
drm/imx: ipuv3-plane: request modeset if plane offsets changed

+125 -134
-12
drivers/gpu/drm/imx/imx-ldb.c
··· 319 319 struct imx_ldb *ldb = imx_ldb_ch->ldb; 320 320 int mux, ret; 321 321 322 - /* 323 - * imx_ldb_encoder_disable is called by 324 - * drm_helper_disable_unused_functions without 325 - * the encoder being enabled before. 326 - */ 327 - if (imx_ldb_ch == &ldb->channel[0] && 328 - (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0) 329 - return; 330 - else if (imx_ldb_ch == &ldb->channel[1] && 331 - (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0) 332 - return; 333 - 334 322 drm_panel_disable(imx_ldb_ch->panel); 335 323 336 324 if (imx_ldb_ch == &ldb->channel[0])
+94 -82
drivers/gpu/drm/imx/ipuv3-plane.c
··· 50 50 DRM_FORMAT_YVYU, 51 51 DRM_FORMAT_YUV420, 52 52 DRM_FORMAT_YVU420, 53 + DRM_FORMAT_YUV422, 54 + DRM_FORMAT_YVU422, 55 + DRM_FORMAT_YUV444, 56 + DRM_FORMAT_YVU444, 57 + DRM_FORMAT_NV12, 58 + DRM_FORMAT_NV16, 53 59 DRM_FORMAT_RGB565, 54 60 }; 55 61 ··· 70 64 { 71 65 struct drm_framebuffer *fb = state->fb; 72 66 struct drm_gem_cma_object *cma_obj; 67 + int x = state->src_x >> 16; 68 + int y = state->src_y >> 16; 73 69 74 70 cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 75 71 BUG_ON(!cma_obj); 76 72 77 - return cma_obj->paddr + fb->offsets[0] + 78 - fb->pitches[0] * (state->src_y >> 16) + 79 - (fb->bits_per_pixel >> 3) * (state->src_x >> 16); 73 + return cma_obj->paddr + fb->offsets[0] + fb->pitches[0] * y + 74 + drm_format_plane_cpp(fb->pixel_format, 0) * x; 80 75 } 81 76 82 77 static inline unsigned long ··· 86 79 struct drm_framebuffer *fb = state->fb; 87 80 struct drm_gem_cma_object *cma_obj; 88 81 unsigned long eba = drm_plane_state_to_eba(state); 82 + int x = state->src_x >> 16; 83 + int y = state->src_y >> 16; 89 84 90 85 cma_obj = drm_fb_cma_get_gem_obj(fb, 1); 91 86 BUG_ON(!cma_obj); 92 87 93 - return cma_obj->paddr + fb->offsets[1] + 94 - fb->pitches[1] * (state->src_y >> 16) / 2 + 95 - (state->src_x >> 16) / 2 - eba; 88 + x /= drm_format_horz_chroma_subsampling(fb->pixel_format); 89 + y /= drm_format_vert_chroma_subsampling(fb->pixel_format); 90 + 91 + return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + 92 + drm_format_plane_cpp(fb->pixel_format, 1) * x - eba; 96 93 } 97 94 98 95 static inline unsigned long ··· 105 94 struct drm_framebuffer *fb = state->fb; 106 95 struct drm_gem_cma_object *cma_obj; 107 96 unsigned long eba = drm_plane_state_to_eba(state); 97 + int x = state->src_x >> 16; 98 + int y = state->src_y >> 16; 108 99 109 100 cma_obj = drm_fb_cma_get_gem_obj(fb, 2); 110 101 BUG_ON(!cma_obj); 111 102 112 - return cma_obj->paddr + fb->offsets[2] + 113 - fb->pitches[2] * (state->src_y >> 16) / 2 + 114 - (state->src_x >> 16) / 2 - eba; 115 - } 103 + x /= drm_format_horz_chroma_subsampling(fb->pixel_format); 104 + y /= drm_format_vert_chroma_subsampling(fb->pixel_format); 116 105 117 - static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane) 118 - { 119 - struct drm_plane *plane = &ipu_plane->base; 120 - struct drm_plane_state *state = plane->state; 121 - struct drm_crtc_state *crtc_state = state->crtc->state; 122 - struct drm_framebuffer *fb = state->fb; 123 - unsigned long eba, ubo, vbo; 124 - int active; 125 - 126 - eba = drm_plane_state_to_eba(state); 127 - 128 - switch (fb->pixel_format) { 129 - case DRM_FORMAT_YUV420: 130 - case DRM_FORMAT_YVU420: 131 - if (!drm_atomic_crtc_needs_modeset(crtc_state)) 132 - break; 133 - 134 - /* 135 - * Multiplanar formats have to meet the following restrictions: 136 - * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO 137 - * - EBA, UBO and VBO are a multiple of 8 138 - * - UBO and VBO are unsigned and not larger than 0xfffff8 139 - * - Only EBA may be changed while scanout is active 140 - * - The strides of U and V planes must be identical. 141 - */ 142 - ubo = drm_plane_state_to_ubo(state); 143 - vbo = drm_plane_state_to_vbo(state); 144 - 145 - if (fb->pixel_format == DRM_FORMAT_YUV420) 146 - ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, 147 - fb->pitches[1], ubo, vbo); 148 - else 149 - ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, 150 - fb->pitches[1], vbo, ubo); 151 - 152 - dev_dbg(ipu_plane->base.dev->dev, 153 - "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, 154 - state->src_x >> 16, state->src_y >> 16); 155 - break; 156 - default: 157 - dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", 158 - eba, state->src_x >> 16, state->src_y >> 16); 159 - 160 - break; 161 - } 162 - 163 - if (!drm_atomic_crtc_needs_modeset(crtc_state)) { 164 - active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); 165 - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); 166 - ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); 167 - } else { 168 - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); 169 - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); 170 - } 106 + return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + 107 + drm_format_plane_cpp(fb->pixel_format, 2) * x - eba; 171 108 } 172 109 173 110 void ipu_plane_put_resources(struct ipu_plane *ipu_plane) ··· 298 339 switch (fb->pixel_format) { 299 340 case DRM_FORMAT_YUV420: 300 341 case DRM_FORMAT_YVU420: 342 + case DRM_FORMAT_YUV422: 343 + case DRM_FORMAT_YVU422: 344 + case DRM_FORMAT_YUV444: 345 + case DRM_FORMAT_YVU444: 301 346 /* 302 347 * Multiplanar formats have to meet the following restrictions: 303 348 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO ··· 310 347 * - Only EBA may be changed while scanout is active 311 348 * - The strides of U and V planes must be identical. 312 349 */ 313 - ubo = drm_plane_state_to_ubo(state); 314 350 vbo = drm_plane_state_to_vbo(state); 315 351 316 - if ((ubo & 0x7) || (vbo & 0x7)) 352 + if (vbo & 0x7 || vbo > 0xfffff8) 317 353 return -EINVAL; 318 354 319 - if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) 320 - return -EINVAL; 321 - 322 - if (old_fb && 323 - (old_fb->pixel_format == DRM_FORMAT_YUV420 || 324 - old_fb->pixel_format == DRM_FORMAT_YVU420)) { 325 - old_ubo = drm_plane_state_to_ubo(old_state); 355 + if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { 326 356 old_vbo = drm_plane_state_to_vbo(old_state); 327 - if (ubo != old_ubo || vbo != old_vbo) 328 - return -EINVAL; 357 + if (vbo != old_vbo) 358 + crtc_state->mode_changed = true; 329 359 } 330 360 331 361 if (fb->pitches[1] != fb->pitches[2]) 332 362 return -EINVAL; 363 + 364 + /* fall-through */ 365 + case DRM_FORMAT_NV12: 366 + case DRM_FORMAT_NV16: 367 + ubo = drm_plane_state_to_ubo(state); 368 + 369 + if (ubo & 0x7 || ubo > 0xfffff8) 370 + return -EINVAL; 371 + 372 + if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { 373 + old_ubo = drm_plane_state_to_ubo(old_state); 374 + if (ubo != old_ubo) 375 + crtc_state->mode_changed = true; 376 + } 333 377 334 378 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) 335 379 return -EINVAL; ··· 369 399 { 370 400 struct ipu_plane *ipu_plane = to_ipu_plane(plane); 371 401 struct drm_plane_state *state = plane->state; 402 + struct drm_crtc_state *crtc_state = state->crtc->state; 403 + struct drm_framebuffer *fb = state->fb; 404 + unsigned long eba, ubo, vbo; 372 405 enum ipu_color_space ics; 406 + int active; 373 407 374 - if (old_state->fb) { 375 - struct drm_crtc_state *crtc_state = state->crtc->state; 408 + eba = drm_plane_state_to_eba(state); 376 409 377 - if (!drm_atomic_crtc_needs_modeset(crtc_state)) { 378 - ipu_plane_atomic_set_base(ipu_plane); 379 - return; 380 - } 410 + if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { 411 + active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); 412 + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); 413 + ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); 414 + return; 381 415 } 382 416 383 417 switch (ipu_plane->dp_flow) { ··· 425 451 ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); 426 452 ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); 427 453 ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]); 428 - ipu_plane_atomic_set_base(ipu_plane); 454 + switch (fb->pixel_format) { 455 + case DRM_FORMAT_YUV420: 456 + case DRM_FORMAT_YVU420: 457 + case DRM_FORMAT_YUV422: 458 + case DRM_FORMAT_YVU422: 459 + case DRM_FORMAT_YUV444: 460 + case DRM_FORMAT_YVU444: 461 + ubo = drm_plane_state_to_ubo(state); 462 + vbo = drm_plane_state_to_vbo(state); 463 + if (fb->pixel_format == DRM_FORMAT_YVU420 || 464 + fb->pixel_format == DRM_FORMAT_YVU422 || 465 + fb->pixel_format == DRM_FORMAT_YVU444) 466 + swap(ubo, vbo); 467 + 468 + ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, 469 + fb->pitches[1], ubo, vbo); 470 + 471 + dev_dbg(ipu_plane->base.dev->dev, 472 + "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, 473 + state->src_x >> 16, state->src_y >> 16); 474 + break; 475 + case DRM_FORMAT_NV12: 476 + case DRM_FORMAT_NV16: 477 + ubo = drm_plane_state_to_ubo(state); 478 + 479 + ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, 480 + fb->pitches[1], ubo, ubo); 481 + 482 + dev_dbg(ipu_plane->base.dev->dev, 483 + "phy = %lu %lu, x = %d, y = %d", eba, ubo, 484 + state->src_x >> 16, state->src_y >> 16); 485 + break; 486 + default: 487 + dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", 488 + eba, state->src_x >> 16, state->src_y >> 16); 489 + break; 490 + } 491 + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); 492 + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); 429 493 ipu_plane_enable(ipu_plane); 430 494 } 431 495
+6 -1
drivers/gpu/ipu-v3/ipu-common.c
··· 88 88 case DRM_FORMAT_YVU420: 89 89 case DRM_FORMAT_YUV422: 90 90 case DRM_FORMAT_YVU422: 91 + case DRM_FORMAT_YUV444: 92 + case DRM_FORMAT_YVU444: 91 93 case DRM_FORMAT_NV12: 92 94 case DRM_FORMAT_NV21: 93 95 case DRM_FORMAT_NV16: ··· 1286 1284 return ret; 1287 1285 } 1288 1286 1289 - for (i = 0; i < IPU_NUM_IRQS; i += 32) 1287 + /* Mask and clear all interrupts */ 1288 + for (i = 0; i < IPU_NUM_IRQS; i += 32) { 1290 1289 ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32)); 1290 + ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32)); 1291 + } 1291 1292 1292 1293 for (i = 0; i < IPU_NUM_IRQS; i += 32) { 1293 1294 gc = irq_get_domain_generic_chip(ipu->domain, i);
+7 -36
drivers/gpu/ipu-v3/ipu-cpmem.c
··· 417 417 } 418 418 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full); 419 419 420 - void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch, 421 - u32 pixel_format, int stride, int height) 422 - { 423 - int fourcc, u_offset, v_offset; 424 - int uv_stride = 0; 425 - 426 - fourcc = v4l2_pix_fmt_to_drm_fourcc(pixel_format); 427 - switch (fourcc) { 428 - case DRM_FORMAT_YUV420: 429 - uv_stride = stride / 2; 430 - u_offset = stride * height; 431 - v_offset = u_offset + (uv_stride * height / 2); 432 - break; 433 - case DRM_FORMAT_YVU420: 434 - uv_stride = stride / 2; 435 - v_offset = stride * height; 436 - u_offset = v_offset + (uv_stride * height / 2); 437 - break; 438 - case DRM_FORMAT_YUV422: 439 - uv_stride = stride / 2; 440 - u_offset = stride * height; 441 - v_offset = u_offset + (uv_stride * height); 442 - break; 443 - case DRM_FORMAT_NV12: 444 - case DRM_FORMAT_NV16: 445 - uv_stride = stride; 446 - u_offset = stride * height; 447 - v_offset = 0; 448 - break; 449 - default: 450 - return; 451 - } 452 - ipu_cpmem_set_yuv_planar_full(ch, uv_stride, u_offset, v_offset); 453 - } 454 - EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); 455 - 456 420 static const struct ipu_rgb def_xrgb_32 = { 457 421 .red = { .offset = 16, .length = 8, }, 458 422 .green = { .offset = 8, .length = 8, }, ··· 551 587 case DRM_FORMAT_YVU422: 552 588 /* pix format */ 553 589 ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1); 590 + /* burst size */ 591 + ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31); 592 + break; 593 + case DRM_FORMAT_YUV444: 594 + case DRM_FORMAT_YVU444: 595 + /* pix format */ 596 + ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0); 554 597 /* burst size */ 555 598 ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31); 556 599 break;
+16
drivers/gpu/ipu-v3/ipu-csi.c
··· 529 529 } 530 530 EXPORT_SYMBOL_GPL(ipu_csi_set_window); 531 531 532 + void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert) 533 + { 534 + unsigned long flags; 535 + u32 reg; 536 + 537 + spin_lock_irqsave(&csi->lock, flags); 538 + 539 + reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL); 540 + reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN); 541 + reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) | 542 + (vert ? CSI_VERT_DOWNSIZE_EN : 0); 543 + ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL); 544 + 545 + spin_unlock_irqrestore(&csi->lock, flags); 546 + } 547 + 532 548 void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active, 533 549 u32 r_value, u32 g_value, u32 b_value, 534 550 u32 pix_clk)
+1 -1
drivers/gpu/ipu-v3/ipu-di.c
··· 535 535 return -EINVAL; 536 536 } 537 537 538 - dev_warn(di->ipu->dev, "videomode adapted for IPU restrictions\n"); 538 + dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n"); 539 539 return 0; 540 540 } 541 541 EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
+1 -2
include/video/imx-ipu-v3.h
··· 247 247 unsigned int uv_stride, 248 248 unsigned int u_offset, 249 249 unsigned int v_offset); 250 - void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch, 251 - u32 pixel_format, int stride, int height); 252 250 int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc); 253 251 int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image); 254 252 void ipu_cpmem_dump(struct ipuv3_channel *ch); ··· 318 320 bool ipu_csi_is_interlaced(struct ipu_csi *csi); 319 321 void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w); 320 322 void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w); 323 + void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert); 321 324 void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active, 322 325 u32 r_value, u32 g_value, u32 b_value, 323 326 u32 pix_clk);