diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sprite.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 737 |
1 files changed, 516 insertions, 221 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 5fd2f7bf3927..abe193815ccc 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "intel_frontbuffer.h" | 40 | #include "intel_frontbuffer.h" |
41 | #include <drm/i915_drm.h> | 41 | #include <drm/i915_drm.h> |
42 | #include "i915_drv.h" | 42 | #include "i915_drv.h" |
43 | #include <drm/drm_color_mgmt.h> | ||
43 | 44 | ||
44 | int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, | 45 | int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, |
45 | int usecs) | 46 | int usecs) |
@@ -275,17 +276,24 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) | |||
275 | src->y2 = (src_y + src_h) << 16; | 276 | src->y2 = (src_y + src_h) << 16; |
276 | 277 | ||
277 | if (fb->format->is_yuv && | 278 | if (fb->format->is_yuv && |
278 | fb->format->format != DRM_FORMAT_NV12 && | ||
279 | (src_x & 1 || src_w & 1)) { | 279 | (src_x & 1 || src_w & 1)) { |
280 | DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", | 280 | DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", |
281 | src_x, src_w); | 281 | src_x, src_w); |
282 | return -EINVAL; | 282 | return -EINVAL; |
283 | } | 283 | } |
284 | 284 | ||
285 | if (fb->format->is_yuv && | ||
286 | fb->format->num_planes > 1 && | ||
287 | (src_y & 1 || src_h & 1)) { | ||
288 | DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of 2 for planar YUV planes\n", | ||
289 | src_y, src_h); | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | |||
285 | return 0; | 293 | return 0; |
286 | } | 294 | } |
287 | 295 | ||
288 | unsigned int | 296 | static unsigned int |
289 | skl_plane_max_stride(struct intel_plane *plane, | 297 | skl_plane_max_stride(struct intel_plane *plane, |
290 | u32 pixel_format, u64 modifier, | 298 | u32 pixel_format, u64 modifier, |
291 | unsigned int rotation) | 299 | unsigned int rotation) |
@@ -302,35 +310,201 @@ skl_plane_max_stride(struct intel_plane *plane, | |||
302 | return min(8192 * cpp, 32768); | 310 | return min(8192 * cpp, 32768); |
303 | } | 311 | } |
304 | 312 | ||
305 | void | 313 | static void |
306 | skl_update_plane(struct intel_plane *plane, | 314 | skl_program_scaler(struct intel_plane *plane, |
307 | const struct intel_crtc_state *crtc_state, | 315 | const struct intel_crtc_state *crtc_state, |
308 | const struct intel_plane_state *plane_state) | 316 | const struct intel_plane_state *plane_state) |
317 | { | ||
318 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | ||
319 | enum pipe pipe = plane->pipe; | ||
320 | int scaler_id = plane_state->scaler_id; | ||
321 | const struct intel_scaler *scaler = | ||
322 | &crtc_state->scaler_state.scalers[scaler_id]; | ||
323 | int crtc_x = plane_state->base.dst.x1; | ||
324 | int crtc_y = plane_state->base.dst.y1; | ||
325 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | ||
326 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | ||
327 | u16 y_hphase, uv_rgb_hphase; | ||
328 | u16 y_vphase, uv_rgb_vphase; | ||
329 | int hscale, vscale; | ||
330 | |||
331 | hscale = drm_rect_calc_hscale(&plane_state->base.src, | ||
332 | &plane_state->base.dst, | ||
333 | 0, INT_MAX); | ||
334 | vscale = drm_rect_calc_vscale(&plane_state->base.src, | ||
335 | &plane_state->base.dst, | ||
336 | 0, INT_MAX); | ||
337 | |||
338 | /* TODO: handle sub-pixel coordinates */ | ||
339 | if (plane_state->base.fb->format->format == DRM_FORMAT_NV12 && | ||
340 | !icl_is_hdr_plane(plane)) { | ||
341 | y_hphase = skl_scaler_calc_phase(1, hscale, false); | ||
342 | y_vphase = skl_scaler_calc_phase(1, vscale, false); | ||
343 | |||
344 | /* MPEG2 chroma siting convention */ | ||
345 | uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true); | ||
346 | uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false); | ||
347 | } else { | ||
348 | /* not used */ | ||
349 | y_hphase = 0; | ||
350 | y_vphase = 0; | ||
351 | |||
352 | uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false); | ||
353 | uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false); | ||
354 | } | ||
355 | |||
356 | I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id), | ||
357 | PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode); | ||
358 | I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id), | ||
359 | PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase)); | ||
360 | I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id), | ||
361 | PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase)); | ||
362 | I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); | ||
363 | I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h); | ||
364 | } | ||
365 | |||
366 | /* Preoffset values for YUV to RGB Conversion */ | ||
367 | #define PREOFF_YUV_TO_RGB_HI 0x1800 | ||
368 | #define PREOFF_YUV_TO_RGB_ME 0x1F00 | ||
369 | #define PREOFF_YUV_TO_RGB_LO 0x1800 | ||
370 | |||
371 | #define ROFF(x) (((x) & 0xffff) << 16) | ||
372 | #define GOFF(x) (((x) & 0xffff) << 0) | ||
373 | #define BOFF(x) (((x) & 0xffff) << 16) | ||
374 | |||
375 | static void | ||
376 | icl_program_input_csc_coeff(const struct intel_crtc_state *crtc_state, | ||
377 | const struct intel_plane_state *plane_state) | ||
378 | { | ||
379 | struct drm_i915_private *dev_priv = | ||
380 | to_i915(plane_state->base.plane->dev); | ||
381 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | ||
382 | enum pipe pipe = crtc->pipe; | ||
383 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | ||
384 | enum plane_id plane_id = plane->id; | ||
385 | |||
386 | static const u16 input_csc_matrix[][9] = { | ||
387 | /* | ||
388 | * BT.601 full range YCbCr -> full range RGB | ||
389 | * The matrix required is : | ||
390 | * [1.000, 0.000, 1.371, | ||
391 | * 1.000, -0.336, -0.698, | ||
392 | * 1.000, 1.732, 0.0000] | ||
393 | */ | ||
394 | [DRM_COLOR_YCBCR_BT601] = { | ||
395 | 0x7AF8, 0x7800, 0x0, | ||
396 | 0x8B28, 0x7800, 0x9AC0, | ||
397 | 0x0, 0x7800, 0x7DD8, | ||
398 | }, | ||
399 | /* | ||
400 | * BT.709 full range YCbCr -> full range RGB | ||
401 | * The matrix required is : | ||
402 | * [1.000, 0.000, 1.574, | ||
403 | * 1.000, -0.187, -0.468, | ||
404 | * 1.000, 1.855, 0.0000] | ||
405 | */ | ||
406 | [DRM_COLOR_YCBCR_BT709] = { | ||
407 | 0x7C98, 0x7800, 0x0, | ||
408 | 0x9EF8, 0x7800, 0xABF8, | ||
409 | 0x0, 0x7800, 0x7ED8, | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | /* Matrix for Limited Range to Full Range Conversion */ | ||
414 | static const u16 input_csc_matrix_lr[][9] = { | ||
415 | /* | ||
416 | * BT.601 Limted range YCbCr -> full range RGB | ||
417 | * The matrix required is : | ||
418 | * [1.164384, 0.000, 1.596370, | ||
419 | * 1.138393, -0.382500, -0.794598, | ||
420 | * 1.138393, 1.971696, 0.0000] | ||
421 | */ | ||
422 | [DRM_COLOR_YCBCR_BT601] = { | ||
423 | 0x7CC8, 0x7950, 0x0, | ||
424 | 0x8CB8, 0x7918, 0x9C40, | ||
425 | 0x0, 0x7918, 0x7FC8, | ||
426 | }, | ||
427 | /* | ||
428 | * BT.709 Limited range YCbCr -> full range RGB | ||
429 | * The matrix required is : | ||
430 | * [1.164, 0.000, 1.833671, | ||
431 | * 1.138393, -0.213249, -0.532909, | ||
432 | * 1.138393, 2.112402, 0.0000] | ||
433 | */ | ||
434 | [DRM_COLOR_YCBCR_BT709] = { | ||
435 | 0x7EA8, 0x7950, 0x0, | ||
436 | 0x8888, 0x7918, 0xADA8, | ||
437 | 0x0, 0x7918, 0x6870, | ||
438 | }, | ||
439 | }; | ||
440 | const u16 *csc; | ||
441 | |||
442 | if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) | ||
443 | csc = input_csc_matrix[plane_state->base.color_encoding]; | ||
444 | else | ||
445 | csc = input_csc_matrix_lr[plane_state->base.color_encoding]; | ||
446 | |||
447 | I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) | | ||
448 | GOFF(csc[1])); | ||
449 | I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2])); | ||
450 | I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) | | ||
451 | GOFF(csc[4])); | ||
452 | I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5])); | ||
453 | I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) | | ||
454 | GOFF(csc[7])); | ||
455 | I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8])); | ||
456 | |||
457 | I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0), | ||
458 | PREOFF_YUV_TO_RGB_HI); | ||
459 | I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), | ||
460 | PREOFF_YUV_TO_RGB_ME); | ||
461 | I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2), | ||
462 | PREOFF_YUV_TO_RGB_LO); | ||
463 | I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0); | ||
464 | I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0); | ||
465 | I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0); | ||
466 | } | ||
467 | |||
468 | static void | ||
469 | skl_program_plane(struct intel_plane *plane, | ||
470 | const struct intel_crtc_state *crtc_state, | ||
471 | const struct intel_plane_state *plane_state, | ||
472 | int color_plane, bool slave, u32 plane_ctl) | ||
309 | { | 473 | { |
310 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 474 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
311 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
312 | enum plane_id plane_id = plane->id; | 475 | enum plane_id plane_id = plane->id; |
313 | enum pipe pipe = plane->pipe; | 476 | enum pipe pipe = plane->pipe; |
314 | u32 plane_ctl = plane_state->ctl; | ||
315 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 477 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
316 | u32 surf_addr = plane_state->color_plane[0].offset; | 478 | u32 surf_addr = plane_state->color_plane[color_plane].offset; |
317 | u32 stride = skl_plane_stride(plane_state, 0); | 479 | u32 stride = skl_plane_stride(plane_state, color_plane); |
318 | u32 aux_stride = skl_plane_stride(plane_state, 1); | 480 | u32 aux_stride = skl_plane_stride(plane_state, 1); |
319 | int crtc_x = plane_state->base.dst.x1; | 481 | int crtc_x = plane_state->base.dst.x1; |
320 | int crtc_y = plane_state->base.dst.y1; | 482 | int crtc_y = plane_state->base.dst.y1; |
321 | uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); | 483 | uint32_t x = plane_state->color_plane[color_plane].x; |
322 | uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); | 484 | uint32_t y = plane_state->color_plane[color_plane].y; |
323 | uint32_t x = plane_state->color_plane[0].x; | ||
324 | uint32_t y = plane_state->color_plane[0].y; | ||
325 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; | 485 | uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; |
326 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; | 486 | uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; |
487 | struct intel_plane *linked = plane_state->linked_plane; | ||
488 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
489 | u8 alpha = plane_state->base.alpha >> 8; | ||
327 | unsigned long irqflags; | 490 | unsigned long irqflags; |
491 | u32 keymsk, keymax; | ||
328 | 492 | ||
329 | /* Sizes are 0 based */ | 493 | /* Sizes are 0 based */ |
330 | src_w--; | 494 | src_w--; |
331 | src_h--; | 495 | src_h--; |
332 | crtc_w--; | 496 | |
333 | crtc_h--; | 497 | keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha); |
498 | |||
499 | keymsk = key->channel_mask & 0x3ffffff; | ||
500 | if (alpha < 0xff) | ||
501 | keymsk |= PLANE_KEYMSK_ALPHA_ENABLE; | ||
502 | |||
503 | /* The scaler will handle the output position */ | ||
504 | if (plane_state->scaler_id >= 0) { | ||
505 | crtc_x = 0; | ||
506 | crtc_y = 0; | ||
507 | } | ||
334 | 508 | ||
335 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 509 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
336 | 510 | ||
@@ -338,71 +512,83 @@ skl_update_plane(struct intel_plane *plane, | |||
338 | I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), | 512 | I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), |
339 | plane_state->color_ctl); | 513 | plane_state->color_ctl); |
340 | 514 | ||
341 | if (key->flags) { | 515 | if (fb->format->is_yuv && icl_is_hdr_plane(plane)) |
342 | I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value); | 516 | icl_program_input_csc_coeff(crtc_state, plane_state); |
343 | I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value); | 517 | |
344 | I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask); | 518 | I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value); |
345 | } | 519 | I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax); |
520 | I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk); | ||
346 | 521 | ||
347 | I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x); | 522 | I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x); |
348 | I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride); | 523 | I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride); |
349 | I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); | 524 | I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); |
350 | I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), | 525 | I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), |
351 | (plane_state->color_plane[1].offset - surf_addr) | aux_stride); | 526 | (plane_state->color_plane[1].offset - surf_addr) | aux_stride); |
352 | I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id), | ||
353 | (plane_state->color_plane[1].y << 16) | | ||
354 | plane_state->color_plane[1].x); | ||
355 | 527 | ||
356 | /* program plane scaler */ | 528 | if (INTEL_GEN(dev_priv) < 11) |
357 | if (plane_state->scaler_id >= 0) { | 529 | I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id), |
358 | int scaler_id = plane_state->scaler_id; | 530 | (plane_state->color_plane[1].y << 16) | |
359 | const struct intel_scaler *scaler = | 531 | plane_state->color_plane[1].x); |
360 | &crtc_state->scaler_state.scalers[scaler_id]; | 532 | |
361 | u16 y_hphase, uv_rgb_hphase; | 533 | if (icl_is_hdr_plane(plane)) { |
362 | u16 y_vphase, uv_rgb_vphase; | 534 | u32 cus_ctl = 0; |
363 | 535 | ||
364 | /* TODO: handle sub-pixel coordinates */ | 536 | if (linked) { |
365 | if (fb->format->format == DRM_FORMAT_NV12) { | 537 | /* Enable and use MPEG-2 chroma siting */ |
366 | y_hphase = skl_scaler_calc_phase(1, false); | 538 | cus_ctl = PLANE_CUS_ENABLE | |
367 | y_vphase = skl_scaler_calc_phase(1, false); | 539 | PLANE_CUS_HPHASE_0 | |
368 | 540 | PLANE_CUS_VPHASE_SIGN_NEGATIVE | | |
369 | /* MPEG2 chroma siting convention */ | 541 | PLANE_CUS_VPHASE_0_25; |
370 | uv_rgb_hphase = skl_scaler_calc_phase(2, true); | 542 | |
371 | uv_rgb_vphase = skl_scaler_calc_phase(2, false); | 543 | if (linked->id == PLANE_SPRITE5) |
372 | } else { | 544 | cus_ctl |= PLANE_CUS_PLANE_7; |
373 | /* not used */ | 545 | else if (linked->id == PLANE_SPRITE4) |
374 | y_hphase = 0; | 546 | cus_ctl |= PLANE_CUS_PLANE_6; |
375 | y_vphase = 0; | 547 | else |
376 | 548 | MISSING_CASE(linked->id); | |
377 | uv_rgb_hphase = skl_scaler_calc_phase(1, false); | ||
378 | uv_rgb_vphase = skl_scaler_calc_phase(1, false); | ||
379 | } | 549 | } |
380 | 550 | ||
381 | I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id), | 551 | I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), cus_ctl); |
382 | PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode); | ||
383 | I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0); | ||
384 | I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id), | ||
385 | PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase)); | ||
386 | I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id), | ||
387 | PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase)); | ||
388 | I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); | ||
389 | I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), | ||
390 | ((crtc_w + 1) << 16)|(crtc_h + 1)); | ||
391 | |||
392 | I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0); | ||
393 | } else { | ||
394 | I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x); | ||
395 | } | 552 | } |
396 | 553 | ||
554 | if (!slave && plane_state->scaler_id >= 0) | ||
555 | skl_program_scaler(plane, crtc_state, plane_state); | ||
556 | |||
557 | I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x); | ||
558 | |||
397 | I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl); | 559 | I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl); |
398 | I915_WRITE_FW(PLANE_SURF(pipe, plane_id), | 560 | I915_WRITE_FW(PLANE_SURF(pipe, plane_id), |
399 | intel_plane_ggtt_offset(plane_state) + surf_addr); | 561 | intel_plane_ggtt_offset(plane_state) + surf_addr); |
400 | POSTING_READ_FW(PLANE_SURF(pipe, plane_id)); | ||
401 | 562 | ||
402 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 563 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
403 | } | 564 | } |
404 | 565 | ||
405 | void | 566 | static void |
567 | skl_update_plane(struct intel_plane *plane, | ||
568 | const struct intel_crtc_state *crtc_state, | ||
569 | const struct intel_plane_state *plane_state) | ||
570 | { | ||
571 | int color_plane = 0; | ||
572 | |||
573 | if (plane_state->linked_plane) { | ||
574 | /* Program the UV plane */ | ||
575 | color_plane = 1; | ||
576 | } | ||
577 | |||
578 | skl_program_plane(plane, crtc_state, plane_state, | ||
579 | color_plane, false, plane_state->ctl); | ||
580 | } | ||
581 | |||
582 | static void | ||
583 | icl_update_slave(struct intel_plane *plane, | ||
584 | const struct intel_crtc_state *crtc_state, | ||
585 | const struct intel_plane_state *plane_state) | ||
586 | { | ||
587 | skl_program_plane(plane, crtc_state, plane_state, 0, true, | ||
588 | plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE); | ||
589 | } | ||
590 | |||
591 | static void | ||
406 | skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) | 592 | skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) |
407 | { | 593 | { |
408 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 594 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
@@ -413,14 +599,12 @@ skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) | |||
413 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 599 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
414 | 600 | ||
415 | I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0); | 601 | I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0); |
416 | |||
417 | I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0); | 602 | I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0); |
418 | POSTING_READ_FW(PLANE_SURF(pipe, plane_id)); | ||
419 | 603 | ||
420 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 604 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
421 | } | 605 | } |
422 | 606 | ||
423 | bool | 607 | static bool |
424 | skl_plane_get_hw_state(struct intel_plane *plane, | 608 | skl_plane_get_hw_state(struct intel_plane *plane, |
425 | enum pipe *pipe) | 609 | enum pipe *pipe) |
426 | { | 610 | { |
@@ -613,7 +797,6 @@ vlv_update_plane(struct intel_plane *plane, | |||
613 | const struct intel_plane_state *plane_state) | 797 | const struct intel_plane_state *plane_state) |
614 | { | 798 | { |
615 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 799 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
616 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
617 | enum pipe pipe = plane->pipe; | 800 | enum pipe pipe = plane->pipe; |
618 | enum plane_id plane_id = plane->id; | 801 | enum plane_id plane_id = plane->id; |
619 | u32 sprctl = plane_state->ctl; | 802 | u32 sprctl = plane_state->ctl; |
@@ -650,10 +833,8 @@ vlv_update_plane(struct intel_plane *plane, | |||
650 | plane_state->color_plane[0].stride); | 833 | plane_state->color_plane[0].stride); |
651 | I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x); | 834 | I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x); |
652 | 835 | ||
653 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 836 | I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x); |
654 | I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x); | 837 | I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset); |
655 | else | ||
656 | I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset); | ||
657 | 838 | ||
658 | I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0); | 839 | I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0); |
659 | 840 | ||
@@ -661,7 +842,6 @@ vlv_update_plane(struct intel_plane *plane, | |||
661 | I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl); | 842 | I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl); |
662 | I915_WRITE_FW(SPSURF(pipe, plane_id), | 843 | I915_WRITE_FW(SPSURF(pipe, plane_id), |
663 | intel_plane_ggtt_offset(plane_state) + sprsurf_offset); | 844 | intel_plane_ggtt_offset(plane_state) + sprsurf_offset); |
664 | POSTING_READ_FW(SPSURF(pipe, plane_id)); | ||
665 | 845 | ||
666 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 846 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
667 | } | 847 | } |
@@ -677,9 +857,7 @@ vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) | |||
677 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | 857 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
678 | 858 | ||
679 | I915_WRITE_FW(SPCNTR(pipe, plane_id), 0); | 859 | I915_WRITE_FW(SPCNTR(pipe, plane_id), 0); |
680 | |||
681 | I915_WRITE_FW(SPSURF(pipe, plane_id), 0); | 860 | I915_WRITE_FW(SPSURF(pipe, plane_id), 0); |
682 | POSTING_READ_FW(SPSURF(pipe, plane_id)); | ||
683 | 861 | ||
684 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 862 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
685 | } | 863 | } |
@@ -774,7 +952,6 @@ ivb_update_plane(struct intel_plane *plane, | |||
774 | const struct intel_plane_state *plane_state) | 952 | const struct intel_plane_state *plane_state) |
775 | { | 953 | { |
776 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 954 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
777 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
778 | enum pipe pipe = plane->pipe; | 955 | enum pipe pipe = plane->pipe; |
779 | u32 sprctl = plane_state->ctl, sprscale = 0; | 956 | u32 sprctl = plane_state->ctl, sprscale = 0; |
780 | u32 sprsurf_offset = plane_state->color_plane[0].offset; | 957 | u32 sprsurf_offset = plane_state->color_plane[0].offset; |
@@ -814,12 +991,12 @@ ivb_update_plane(struct intel_plane *plane, | |||
814 | 991 | ||
815 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET | 992 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
816 | * register */ | 993 | * register */ |
817 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) | 994 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { |
818 | I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x); | 995 | I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x); |
819 | else if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 996 | } else { |
820 | I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x); | 997 | I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x); |
821 | else | ||
822 | I915_WRITE_FW(SPRLINOFF(pipe), linear_offset); | 998 | I915_WRITE_FW(SPRLINOFF(pipe), linear_offset); |
999 | } | ||
823 | 1000 | ||
824 | I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); | 1001 | I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); |
825 | if (IS_IVYBRIDGE(dev_priv)) | 1002 | if (IS_IVYBRIDGE(dev_priv)) |
@@ -827,7 +1004,6 @@ ivb_update_plane(struct intel_plane *plane, | |||
827 | I915_WRITE_FW(SPRCTL(pipe), sprctl); | 1004 | I915_WRITE_FW(SPRCTL(pipe), sprctl); |
828 | I915_WRITE_FW(SPRSURF(pipe), | 1005 | I915_WRITE_FW(SPRSURF(pipe), |
829 | intel_plane_ggtt_offset(plane_state) + sprsurf_offset); | 1006 | intel_plane_ggtt_offset(plane_state) + sprsurf_offset); |
830 | POSTING_READ_FW(SPRSURF(pipe)); | ||
831 | 1007 | ||
832 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 1008 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
833 | } | 1009 | } |
@@ -845,9 +1021,7 @@ ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) | |||
845 | /* Can't leave the scaler enabled... */ | 1021 | /* Can't leave the scaler enabled... */ |
846 | if (IS_IVYBRIDGE(dev_priv)) | 1022 | if (IS_IVYBRIDGE(dev_priv)) |
847 | I915_WRITE_FW(SPRSCALE(pipe), 0); | 1023 | I915_WRITE_FW(SPRSCALE(pipe), 0); |
848 | |||
849 | I915_WRITE_FW(SPRSURF(pipe), 0); | 1024 | I915_WRITE_FW(SPRSURF(pipe), 0); |
850 | POSTING_READ_FW(SPRSURF(pipe)); | ||
851 | 1025 | ||
852 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 1026 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
853 | } | 1027 | } |
@@ -946,7 +1120,6 @@ g4x_update_plane(struct intel_plane *plane, | |||
946 | const struct intel_plane_state *plane_state) | 1120 | const struct intel_plane_state *plane_state) |
947 | { | 1121 | { |
948 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 1122 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
949 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
950 | enum pipe pipe = plane->pipe; | 1123 | enum pipe pipe = plane->pipe; |
951 | u32 dvscntr = plane_state->ctl, dvsscale = 0; | 1124 | u32 dvscntr = plane_state->ctl, dvsscale = 0; |
952 | u32 dvssurf_offset = plane_state->color_plane[0].offset; | 1125 | u32 dvssurf_offset = plane_state->color_plane[0].offset; |
@@ -984,17 +1157,14 @@ g4x_update_plane(struct intel_plane *plane, | |||
984 | I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride); | 1157 | I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride); |
985 | I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x); | 1158 | I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x); |
986 | 1159 | ||
987 | if (fb->modifier == I915_FORMAT_MOD_X_TILED) | 1160 | I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x); |
988 | I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x); | 1161 | I915_WRITE_FW(DVSLINOFF(pipe), linear_offset); |
989 | else | ||
990 | I915_WRITE_FW(DVSLINOFF(pipe), linear_offset); | ||
991 | 1162 | ||
992 | I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); | 1163 | I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); |
993 | I915_WRITE_FW(DVSSCALE(pipe), dvsscale); | 1164 | I915_WRITE_FW(DVSSCALE(pipe), dvsscale); |
994 | I915_WRITE_FW(DVSCNTR(pipe), dvscntr); | 1165 | I915_WRITE_FW(DVSCNTR(pipe), dvscntr); |
995 | I915_WRITE_FW(DVSSURF(pipe), | 1166 | I915_WRITE_FW(DVSSURF(pipe), |
996 | intel_plane_ggtt_offset(plane_state) + dvssurf_offset); | 1167 | intel_plane_ggtt_offset(plane_state) + dvssurf_offset); |
997 | POSTING_READ_FW(DVSSURF(pipe)); | ||
998 | 1168 | ||
999 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 1169 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
1000 | } | 1170 | } |
@@ -1011,9 +1181,7 @@ g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) | |||
1011 | I915_WRITE_FW(DVSCNTR(pipe), 0); | 1181 | I915_WRITE_FW(DVSCNTR(pipe), 0); |
1012 | /* Disable the scaler */ | 1182 | /* Disable the scaler */ |
1013 | I915_WRITE_FW(DVSSCALE(pipe), 0); | 1183 | I915_WRITE_FW(DVSSCALE(pipe), 0); |
1014 | |||
1015 | I915_WRITE_FW(DVSSURF(pipe), 0); | 1184 | I915_WRITE_FW(DVSSURF(pipe), 0); |
1016 | POSTING_READ_FW(DVSSURF(pipe)); | ||
1017 | 1185 | ||
1018 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | 1186 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
1019 | } | 1187 | } |
@@ -1039,6 +1207,19 @@ g4x_plane_get_hw_state(struct intel_plane *plane, | |||
1039 | return ret; | 1207 | return ret; |
1040 | } | 1208 | } |
1041 | 1209 | ||
1210 | static bool intel_fb_scalable(const struct drm_framebuffer *fb) | ||
1211 | { | ||
1212 | if (!fb) | ||
1213 | return false; | ||
1214 | |||
1215 | switch (fb->format->format) { | ||
1216 | case DRM_FORMAT_C8: | ||
1217 | return false; | ||
1218 | default: | ||
1219 | return true; | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1042 | static int | 1223 | static int |
1043 | g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, | 1224 | g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, |
1044 | struct intel_plane_state *plane_state) | 1225 | struct intel_plane_state *plane_state) |
@@ -1106,18 +1287,18 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, | |||
1106 | { | 1287 | { |
1107 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | 1288 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); |
1108 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 1289 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
1109 | int max_scale, min_scale; | 1290 | int min_scale = DRM_PLANE_HELPER_NO_SCALING; |
1291 | int max_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
1110 | int ret; | 1292 | int ret; |
1111 | 1293 | ||
1112 | if (INTEL_GEN(dev_priv) < 7) { | 1294 | if (intel_fb_scalable(plane_state->base.fb)) { |
1113 | min_scale = 1; | 1295 | if (INTEL_GEN(dev_priv) < 7) { |
1114 | max_scale = 16 << 16; | 1296 | min_scale = 1; |
1115 | } else if (IS_IVYBRIDGE(dev_priv)) { | 1297 | max_scale = 16 << 16; |
1116 | min_scale = 1; | 1298 | } else if (IS_IVYBRIDGE(dev_priv)) { |
1117 | max_scale = 2 << 16; | 1299 | min_scale = 1; |
1118 | } else { | 1300 | max_scale = 2 << 16; |
1119 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | 1301 | } |
1120 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
1121 | } | 1302 | } |
1122 | 1303 | ||
1123 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, | 1304 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, |
@@ -1204,6 +1385,8 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, | |||
1204 | static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, | 1385 | static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, |
1205 | const struct intel_plane_state *plane_state) | 1386 | const struct intel_plane_state *plane_state) |
1206 | { | 1387 | { |
1388 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | ||
1389 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | ||
1207 | const struct drm_framebuffer *fb = plane_state->base.fb; | 1390 | const struct drm_framebuffer *fb = plane_state->base.fb; |
1208 | unsigned int rotation = plane_state->base.rotation; | 1391 | unsigned int rotation = plane_state->base.rotation; |
1209 | struct drm_format_name_buf format_name; | 1392 | struct drm_format_name_buf format_name; |
@@ -1232,13 +1415,17 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, | |||
1232 | } | 1415 | } |
1233 | 1416 | ||
1234 | /* | 1417 | /* |
1235 | * 90/270 is not allowed with RGB64 16:16:16:16, | 1418 | * 90/270 is not allowed with RGB64 16:16:16:16 and |
1236 | * RGB 16-bit 5:6:5, and Indexed 8-bit. | 1419 | * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards. |
1237 | * TBD: Add RGB64 case once its added in supported format list. | 1420 | * TBD: Add RGB64 case once its added in supported format |
1421 | * list. | ||
1238 | */ | 1422 | */ |
1239 | switch (fb->format->format) { | 1423 | switch (fb->format->format) { |
1240 | case DRM_FORMAT_C8: | ||
1241 | case DRM_FORMAT_RGB565: | 1424 | case DRM_FORMAT_RGB565: |
1425 | if (INTEL_GEN(dev_priv) >= 11) | ||
1426 | break; | ||
1427 | /* fall through */ | ||
1428 | case DRM_FORMAT_C8: | ||
1242 | DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", | 1429 | DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", |
1243 | drm_get_format_name(fb->format->format, | 1430 | drm_get_format_name(fb->format->format, |
1244 | &format_name)); | 1431 | &format_name)); |
@@ -1292,12 +1479,31 @@ static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_s | |||
1292 | return 0; | 1479 | return 0; |
1293 | } | 1480 | } |
1294 | 1481 | ||
1295 | int skl_plane_check(struct intel_crtc_state *crtc_state, | 1482 | static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state) |
1296 | struct intel_plane_state *plane_state) | 1483 | { |
1484 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
1485 | unsigned int rotation = plane_state->base.rotation; | ||
1486 | int src_w = drm_rect_width(&plane_state->base.src) >> 16; | ||
1487 | |||
1488 | /* Display WA #1106 */ | ||
1489 | if (fb->format->format == DRM_FORMAT_NV12 && src_w & 3 && | ||
1490 | (rotation == DRM_MODE_ROTATE_270 || | ||
1491 | rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) { | ||
1492 | DRM_DEBUG_KMS("src width must be multiple of 4 for rotated NV12\n"); | ||
1493 | return -EINVAL; | ||
1494 | } | ||
1495 | |||
1496 | return 0; | ||
1497 | } | ||
1498 | |||
1499 | static int skl_plane_check(struct intel_crtc_state *crtc_state, | ||
1500 | struct intel_plane_state *plane_state) | ||
1297 | { | 1501 | { |
1298 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); | 1502 | struct intel_plane *plane = to_intel_plane(plane_state->base.plane); |
1299 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); | 1503 | struct drm_i915_private *dev_priv = to_i915(plane->base.dev); |
1300 | int max_scale, min_scale; | 1504 | const struct drm_framebuffer *fb = plane_state->base.fb; |
1505 | int min_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
1506 | int max_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
1301 | int ret; | 1507 | int ret; |
1302 | 1508 | ||
1303 | ret = skl_plane_check_fb(crtc_state, plane_state); | 1509 | ret = skl_plane_check_fb(crtc_state, plane_state); |
@@ -1305,15 +1511,9 @@ int skl_plane_check(struct intel_crtc_state *crtc_state, | |||
1305 | return ret; | 1511 | return ret; |
1306 | 1512 | ||
1307 | /* use scaler when colorkey is not required */ | 1513 | /* use scaler when colorkey is not required */ |
1308 | if (!plane_state->ckey.flags) { | 1514 | if (!plane_state->ckey.flags && intel_fb_scalable(fb)) { |
1309 | const struct drm_framebuffer *fb = plane_state->base.fb; | ||
1310 | |||
1311 | min_scale = 1; | 1515 | min_scale = 1; |
1312 | max_scale = skl_max_scale(crtc_state, | 1516 | max_scale = skl_max_scale(crtc_state, fb->format->format); |
1313 | fb ? fb->format->format : 0); | ||
1314 | } else { | ||
1315 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
1316 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
1317 | } | 1517 | } |
1318 | 1518 | ||
1319 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, | 1519 | ret = drm_atomic_helper_check_plane_state(&plane_state->base, |
@@ -1334,10 +1534,18 @@ int skl_plane_check(struct intel_crtc_state *crtc_state, | |||
1334 | if (ret) | 1534 | if (ret) |
1335 | return ret; | 1535 | return ret; |
1336 | 1536 | ||
1537 | ret = skl_plane_check_nv12_rotation(plane_state); | ||
1538 | if (ret) | ||
1539 | return ret; | ||
1540 | |||
1337 | ret = skl_check_plane_surface(plane_state); | 1541 | ret = skl_check_plane_surface(plane_state); |
1338 | if (ret) | 1542 | if (ret) |
1339 | return ret; | 1543 | return ret; |
1340 | 1544 | ||
1545 | /* HW only has 8 bits pixel precision, disable plane if invisible */ | ||
1546 | if (!(plane_state->base.alpha >> 8)) | ||
1547 | plane_state->base.visible = false; | ||
1548 | |||
1341 | plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); | 1549 | plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); |
1342 | 1550 | ||
1343 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) | 1551 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) |
@@ -1502,24 +1710,30 @@ static const uint32_t vlv_plane_formats[] = { | |||
1502 | DRM_FORMAT_VYUY, | 1710 | DRM_FORMAT_VYUY, |
1503 | }; | 1711 | }; |
1504 | 1712 | ||
1505 | static uint32_t skl_plane_formats[] = { | 1713 | static const uint32_t skl_plane_formats[] = { |
1714 | DRM_FORMAT_C8, | ||
1506 | DRM_FORMAT_RGB565, | 1715 | DRM_FORMAT_RGB565, |
1507 | DRM_FORMAT_ABGR8888, | ||
1508 | DRM_FORMAT_ARGB8888, | ||
1509 | DRM_FORMAT_XBGR8888, | ||
1510 | DRM_FORMAT_XRGB8888, | 1716 | DRM_FORMAT_XRGB8888, |
1717 | DRM_FORMAT_XBGR8888, | ||
1718 | DRM_FORMAT_ARGB8888, | ||
1719 | DRM_FORMAT_ABGR8888, | ||
1720 | DRM_FORMAT_XRGB2101010, | ||
1721 | DRM_FORMAT_XBGR2101010, | ||
1511 | DRM_FORMAT_YUYV, | 1722 | DRM_FORMAT_YUYV, |
1512 | DRM_FORMAT_YVYU, | 1723 | DRM_FORMAT_YVYU, |
1513 | DRM_FORMAT_UYVY, | 1724 | DRM_FORMAT_UYVY, |
1514 | DRM_FORMAT_VYUY, | 1725 | DRM_FORMAT_VYUY, |
1515 | }; | 1726 | }; |
1516 | 1727 | ||
1517 | static uint32_t skl_planar_formats[] = { | 1728 | static const uint32_t skl_planar_formats[] = { |
1729 | DRM_FORMAT_C8, | ||
1518 | DRM_FORMAT_RGB565, | 1730 | DRM_FORMAT_RGB565, |
1519 | DRM_FORMAT_ABGR8888, | ||
1520 | DRM_FORMAT_ARGB8888, | ||
1521 | DRM_FORMAT_XBGR8888, | ||
1522 | DRM_FORMAT_XRGB8888, | 1731 | DRM_FORMAT_XRGB8888, |
1732 | DRM_FORMAT_XBGR8888, | ||
1733 | DRM_FORMAT_ARGB8888, | ||
1734 | DRM_FORMAT_ABGR8888, | ||
1735 | DRM_FORMAT_XRGB2101010, | ||
1736 | DRM_FORMAT_XBGR2101010, | ||
1523 | DRM_FORMAT_YUYV, | 1737 | DRM_FORMAT_YUYV, |
1524 | DRM_FORMAT_YVYU, | 1738 | DRM_FORMAT_YVYU, |
1525 | DRM_FORMAT_UYVY, | 1739 | DRM_FORMAT_UYVY, |
@@ -1724,8 +1938,36 @@ static const struct drm_plane_funcs skl_plane_funcs = { | |||
1724 | .format_mod_supported = skl_plane_format_mod_supported, | 1938 | .format_mod_supported = skl_plane_format_mod_supported, |
1725 | }; | 1939 | }; |
1726 | 1940 | ||
1727 | bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, | 1941 | static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv, |
1728 | enum pipe pipe, enum plane_id plane_id) | 1942 | enum pipe pipe, enum plane_id plane_id) |
1943 | { | ||
1944 | if (!HAS_FBC(dev_priv)) | ||
1945 | return false; | ||
1946 | |||
1947 | return pipe == PIPE_A && plane_id == PLANE_PRIMARY; | ||
1948 | } | ||
1949 | |||
1950 | static bool skl_plane_has_planar(struct drm_i915_private *dev_priv, | ||
1951 | enum pipe pipe, enum plane_id plane_id) | ||
1952 | { | ||
1953 | if (INTEL_GEN(dev_priv) >= 11) | ||
1954 | return plane_id <= PLANE_SPRITE3; | ||
1955 | |||
1956 | /* Display WA #0870: skl, bxt */ | ||
1957 | if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv)) | ||
1958 | return false; | ||
1959 | |||
1960 | if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C) | ||
1961 | return false; | ||
1962 | |||
1963 | if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0) | ||
1964 | return false; | ||
1965 | |||
1966 | return true; | ||
1967 | } | ||
1968 | |||
1969 | static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, | ||
1970 | enum pipe pipe, enum plane_id plane_id) | ||
1729 | { | 1971 | { |
1730 | if (plane_id == PLANE_CURSOR) | 1972 | if (plane_id == PLANE_CURSOR) |
1731 | return false; | 1973 | return false; |
@@ -1742,109 +1984,173 @@ bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, | |||
1742 | } | 1984 | } |
1743 | 1985 | ||
1744 | struct intel_plane * | 1986 | struct intel_plane * |
1745 | intel_sprite_plane_create(struct drm_i915_private *dev_priv, | 1987 | skl_universal_plane_create(struct drm_i915_private *dev_priv, |
1746 | enum pipe pipe, int plane) | 1988 | enum pipe pipe, enum plane_id plane_id) |
1747 | { | 1989 | { |
1748 | struct intel_plane *intel_plane = NULL; | 1990 | struct intel_plane *plane; |
1749 | struct intel_plane_state *state = NULL; | 1991 | enum drm_plane_type plane_type; |
1750 | const struct drm_plane_funcs *plane_funcs; | ||
1751 | unsigned long possible_crtcs; | ||
1752 | const uint32_t *plane_formats; | ||
1753 | const uint64_t *modifiers; | ||
1754 | unsigned int supported_rotations; | 1992 | unsigned int supported_rotations; |
1755 | int num_plane_formats; | 1993 | unsigned int possible_crtcs; |
1994 | const u64 *modifiers; | ||
1995 | const u32 *formats; | ||
1996 | int num_formats; | ||
1756 | int ret; | 1997 | int ret; |
1757 | 1998 | ||
1758 | intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); | 1999 | plane = intel_plane_alloc(); |
1759 | if (!intel_plane) { | 2000 | if (IS_ERR(plane)) |
1760 | ret = -ENOMEM; | 2001 | return plane; |
1761 | goto fail; | 2002 | |
2003 | plane->pipe = pipe; | ||
2004 | plane->id = plane_id; | ||
2005 | plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id); | ||
2006 | |||
2007 | plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id); | ||
2008 | if (plane->has_fbc) { | ||
2009 | struct intel_fbc *fbc = &dev_priv->fbc; | ||
2010 | |||
2011 | fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; | ||
1762 | } | 2012 | } |
1763 | 2013 | ||
1764 | state = intel_create_plane_state(&intel_plane->base); | 2014 | plane->max_stride = skl_plane_max_stride; |
1765 | if (!state) { | 2015 | plane->update_plane = skl_update_plane; |
1766 | ret = -ENOMEM; | 2016 | plane->disable_plane = skl_disable_plane; |
1767 | goto fail; | 2017 | plane->get_hw_state = skl_plane_get_hw_state; |
2018 | plane->check_plane = skl_plane_check; | ||
2019 | if (icl_is_nv12_y_plane(plane_id)) | ||
2020 | plane->update_slave = icl_update_slave; | ||
2021 | |||
2022 | if (skl_plane_has_planar(dev_priv, pipe, plane_id)) { | ||
2023 | formats = skl_planar_formats; | ||
2024 | num_formats = ARRAY_SIZE(skl_planar_formats); | ||
2025 | } else { | ||
2026 | formats = skl_plane_formats; | ||
2027 | num_formats = ARRAY_SIZE(skl_plane_formats); | ||
1768 | } | 2028 | } |
1769 | intel_plane->base.state = &state->base; | ||
1770 | 2029 | ||
1771 | if (INTEL_GEN(dev_priv) >= 9) { | 2030 | plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id); |
1772 | state->scaler_id = -1; | 2031 | if (plane->has_ccs) |
2032 | modifiers = skl_plane_format_modifiers_ccs; | ||
2033 | else | ||
2034 | modifiers = skl_plane_format_modifiers_noccs; | ||
1773 | 2035 | ||
1774 | intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, | 2036 | if (plane_id == PLANE_PRIMARY) |
1775 | PLANE_SPRITE0 + plane); | 2037 | plane_type = DRM_PLANE_TYPE_PRIMARY; |
2038 | else | ||
2039 | plane_type = DRM_PLANE_TYPE_OVERLAY; | ||
1776 | 2040 | ||
1777 | intel_plane->max_stride = skl_plane_max_stride; | 2041 | possible_crtcs = BIT(pipe); |
1778 | intel_plane->update_plane = skl_update_plane; | ||
1779 | intel_plane->disable_plane = skl_disable_plane; | ||
1780 | intel_plane->get_hw_state = skl_plane_get_hw_state; | ||
1781 | intel_plane->check_plane = skl_plane_check; | ||
1782 | 2042 | ||
1783 | if (skl_plane_has_planar(dev_priv, pipe, | 2043 | ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, |
1784 | PLANE_SPRITE0 + plane)) { | 2044 | possible_crtcs, &skl_plane_funcs, |
1785 | plane_formats = skl_planar_formats; | 2045 | formats, num_formats, modifiers, |
1786 | num_plane_formats = ARRAY_SIZE(skl_planar_formats); | 2046 | plane_type, |
1787 | } else { | 2047 | "plane %d%c", plane_id + 1, |
1788 | plane_formats = skl_plane_formats; | 2048 | pipe_name(pipe)); |
1789 | num_plane_formats = ARRAY_SIZE(skl_plane_formats); | 2049 | if (ret) |
1790 | } | 2050 | goto fail; |
1791 | 2051 | ||
1792 | if (intel_plane->has_ccs) | 2052 | supported_rotations = |
1793 | modifiers = skl_plane_format_modifiers_ccs; | 2053 | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | |
1794 | else | 2054 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; |
1795 | modifiers = skl_plane_format_modifiers_noccs; | 2055 | |
1796 | 2056 | if (INTEL_GEN(dev_priv) >= 10) | |
1797 | plane_funcs = &skl_plane_funcs; | 2057 | supported_rotations |= DRM_MODE_REFLECT_X; |
1798 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | 2058 | |
1799 | intel_plane->max_stride = i9xx_plane_max_stride; | 2059 | drm_plane_create_rotation_property(&plane->base, |
1800 | intel_plane->update_plane = vlv_update_plane; | 2060 | DRM_MODE_ROTATE_0, |
1801 | intel_plane->disable_plane = vlv_disable_plane; | 2061 | supported_rotations); |
1802 | intel_plane->get_hw_state = vlv_plane_get_hw_state; | 2062 | |
1803 | intel_plane->check_plane = vlv_sprite_check; | 2063 | drm_plane_create_color_properties(&plane->base, |
1804 | 2064 | BIT(DRM_COLOR_YCBCR_BT601) | | |
1805 | plane_formats = vlv_plane_formats; | 2065 | BIT(DRM_COLOR_YCBCR_BT709), |
1806 | num_plane_formats = ARRAY_SIZE(vlv_plane_formats); | 2066 | BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | |
2067 | BIT(DRM_COLOR_YCBCR_FULL_RANGE), | ||
2068 | DRM_COLOR_YCBCR_BT709, | ||
2069 | DRM_COLOR_YCBCR_LIMITED_RANGE); | ||
2070 | |||
2071 | drm_plane_create_alpha_property(&plane->base); | ||
2072 | drm_plane_create_blend_mode_property(&plane->base, | ||
2073 | BIT(DRM_MODE_BLEND_PIXEL_NONE) | | ||
2074 | BIT(DRM_MODE_BLEND_PREMULTI) | | ||
2075 | BIT(DRM_MODE_BLEND_COVERAGE)); | ||
2076 | |||
2077 | drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); | ||
2078 | |||
2079 | return plane; | ||
2080 | |||
2081 | fail: | ||
2082 | intel_plane_free(plane); | ||
2083 | |||
2084 | return ERR_PTR(ret); | ||
2085 | } | ||
2086 | |||
2087 | struct intel_plane * | ||
2088 | intel_sprite_plane_create(struct drm_i915_private *dev_priv, | ||
2089 | enum pipe pipe, int sprite) | ||
2090 | { | ||
2091 | struct intel_plane *plane; | ||
2092 | const struct drm_plane_funcs *plane_funcs; | ||
2093 | unsigned long possible_crtcs; | ||
2094 | unsigned int supported_rotations; | ||
2095 | const u64 *modifiers; | ||
2096 | const u32 *formats; | ||
2097 | int num_formats; | ||
2098 | int ret; | ||
2099 | |||
2100 | if (INTEL_GEN(dev_priv) >= 9) | ||
2101 | return skl_universal_plane_create(dev_priv, pipe, | ||
2102 | PLANE_SPRITE0 + sprite); | ||
2103 | |||
2104 | plane = intel_plane_alloc(); | ||
2105 | if (IS_ERR(plane)) | ||
2106 | return plane; | ||
2107 | |||
2108 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | ||
2109 | plane->max_stride = i9xx_plane_max_stride; | ||
2110 | plane->update_plane = vlv_update_plane; | ||
2111 | plane->disable_plane = vlv_disable_plane; | ||
2112 | plane->get_hw_state = vlv_plane_get_hw_state; | ||
2113 | plane->check_plane = vlv_sprite_check; | ||
2114 | |||
2115 | formats = vlv_plane_formats; | ||
2116 | num_formats = ARRAY_SIZE(vlv_plane_formats); | ||
1807 | modifiers = i9xx_plane_format_modifiers; | 2117 | modifiers = i9xx_plane_format_modifiers; |
1808 | 2118 | ||
1809 | plane_funcs = &vlv_sprite_funcs; | 2119 | plane_funcs = &vlv_sprite_funcs; |
1810 | } else if (INTEL_GEN(dev_priv) >= 7) { | 2120 | } else if (INTEL_GEN(dev_priv) >= 7) { |
1811 | intel_plane->max_stride = g4x_sprite_max_stride; | 2121 | plane->max_stride = g4x_sprite_max_stride; |
1812 | intel_plane->update_plane = ivb_update_plane; | 2122 | plane->update_plane = ivb_update_plane; |
1813 | intel_plane->disable_plane = ivb_disable_plane; | 2123 | plane->disable_plane = ivb_disable_plane; |
1814 | intel_plane->get_hw_state = ivb_plane_get_hw_state; | 2124 | plane->get_hw_state = ivb_plane_get_hw_state; |
1815 | intel_plane->check_plane = g4x_sprite_check; | 2125 | plane->check_plane = g4x_sprite_check; |
1816 | 2126 | ||
1817 | plane_formats = snb_plane_formats; | 2127 | formats = snb_plane_formats; |
1818 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); | 2128 | num_formats = ARRAY_SIZE(snb_plane_formats); |
1819 | modifiers = i9xx_plane_format_modifiers; | 2129 | modifiers = i9xx_plane_format_modifiers; |
1820 | 2130 | ||
1821 | plane_funcs = &snb_sprite_funcs; | 2131 | plane_funcs = &snb_sprite_funcs; |
1822 | } else { | 2132 | } else { |
1823 | intel_plane->max_stride = g4x_sprite_max_stride; | 2133 | plane->max_stride = g4x_sprite_max_stride; |
1824 | intel_plane->update_plane = g4x_update_plane; | 2134 | plane->update_plane = g4x_update_plane; |
1825 | intel_plane->disable_plane = g4x_disable_plane; | 2135 | plane->disable_plane = g4x_disable_plane; |
1826 | intel_plane->get_hw_state = g4x_plane_get_hw_state; | 2136 | plane->get_hw_state = g4x_plane_get_hw_state; |
1827 | intel_plane->check_plane = g4x_sprite_check; | 2137 | plane->check_plane = g4x_sprite_check; |
1828 | 2138 | ||
1829 | modifiers = i9xx_plane_format_modifiers; | 2139 | modifiers = i9xx_plane_format_modifiers; |
1830 | if (IS_GEN6(dev_priv)) { | 2140 | if (IS_GEN6(dev_priv)) { |
1831 | plane_formats = snb_plane_formats; | 2141 | formats = snb_plane_formats; |
1832 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); | 2142 | num_formats = ARRAY_SIZE(snb_plane_formats); |
1833 | 2143 | ||
1834 | plane_funcs = &snb_sprite_funcs; | 2144 | plane_funcs = &snb_sprite_funcs; |
1835 | } else { | 2145 | } else { |
1836 | plane_formats = g4x_plane_formats; | 2146 | formats = g4x_plane_formats; |
1837 | num_plane_formats = ARRAY_SIZE(g4x_plane_formats); | 2147 | num_formats = ARRAY_SIZE(g4x_plane_formats); |
1838 | 2148 | ||
1839 | plane_funcs = &g4x_sprite_funcs; | 2149 | plane_funcs = &g4x_sprite_funcs; |
1840 | } | 2150 | } |
1841 | } | 2151 | } |
1842 | 2152 | ||
1843 | if (INTEL_GEN(dev_priv) >= 9) { | 2153 | if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { |
1844 | supported_rotations = | ||
1845 | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | | ||
1846 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; | ||
1847 | } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { | ||
1848 | supported_rotations = | 2154 | supported_rotations = |
1849 | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | | 2155 | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | |
1850 | DRM_MODE_REFLECT_X; | 2156 | DRM_MODE_REFLECT_X; |
@@ -1853,35 +2159,25 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1853 | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; | 2159 | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; |
1854 | } | 2160 | } |
1855 | 2161 | ||
1856 | intel_plane->pipe = pipe; | 2162 | plane->pipe = pipe; |
1857 | intel_plane->i9xx_plane = plane; | 2163 | plane->id = PLANE_SPRITE0 + sprite; |
1858 | intel_plane->id = PLANE_SPRITE0 + plane; | 2164 | plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id); |
1859 | intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id); | ||
1860 | 2165 | ||
1861 | possible_crtcs = (1 << pipe); | 2166 | possible_crtcs = BIT(pipe); |
1862 | 2167 | ||
1863 | if (INTEL_GEN(dev_priv) >= 9) | 2168 | ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, |
1864 | ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base, | 2169 | possible_crtcs, plane_funcs, |
1865 | possible_crtcs, plane_funcs, | 2170 | formats, num_formats, modifiers, |
1866 | plane_formats, num_plane_formats, | 2171 | DRM_PLANE_TYPE_OVERLAY, |
1867 | modifiers, | 2172 | "sprite %c", sprite_name(pipe, sprite)); |
1868 | DRM_PLANE_TYPE_OVERLAY, | ||
1869 | "plane %d%c", plane + 2, pipe_name(pipe)); | ||
1870 | else | ||
1871 | ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base, | ||
1872 | possible_crtcs, plane_funcs, | ||
1873 | plane_formats, num_plane_formats, | ||
1874 | modifiers, | ||
1875 | DRM_PLANE_TYPE_OVERLAY, | ||
1876 | "sprite %c", sprite_name(pipe, plane)); | ||
1877 | if (ret) | 2173 | if (ret) |
1878 | goto fail; | 2174 | goto fail; |
1879 | 2175 | ||
1880 | drm_plane_create_rotation_property(&intel_plane->base, | 2176 | drm_plane_create_rotation_property(&plane->base, |
1881 | DRM_MODE_ROTATE_0, | 2177 | DRM_MODE_ROTATE_0, |
1882 | supported_rotations); | 2178 | supported_rotations); |
1883 | 2179 | ||
1884 | drm_plane_create_color_properties(&intel_plane->base, | 2180 | drm_plane_create_color_properties(&plane->base, |
1885 | BIT(DRM_COLOR_YCBCR_BT601) | | 2181 | BIT(DRM_COLOR_YCBCR_BT601) | |
1886 | BIT(DRM_COLOR_YCBCR_BT709), | 2182 | BIT(DRM_COLOR_YCBCR_BT709), |
1887 | BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | | 2183 | BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | |
@@ -1889,13 +2185,12 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1889 | DRM_COLOR_YCBCR_BT709, | 2185 | DRM_COLOR_YCBCR_BT709, |
1890 | DRM_COLOR_YCBCR_LIMITED_RANGE); | 2186 | DRM_COLOR_YCBCR_LIMITED_RANGE); |
1891 | 2187 | ||
1892 | drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); | 2188 | drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); |
1893 | 2189 | ||
1894 | return intel_plane; | 2190 | return plane; |
1895 | 2191 | ||
1896 | fail: | 2192 | fail: |
1897 | kfree(state); | 2193 | intel_plane_free(plane); |
1898 | kfree(intel_plane); | ||
1899 | 2194 | ||
1900 | return ERR_PTR(ret); | 2195 | return ERR_PTR(ret); |
1901 | } | 2196 | } |