1a649c2abSJani Nikula /* 2a649c2abSJani Nikula * Copyright © 2014 Intel Corporation 3a649c2abSJani Nikula * 4a649c2abSJani Nikula * Permission is hereby granted, free of charge, to any person obtaining a 5a649c2abSJani Nikula * copy of this software and associated documentation files (the "Software"), 6a649c2abSJani Nikula * to deal in the Software without restriction, including without limitation 7a649c2abSJani Nikula * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8a649c2abSJani Nikula * and/or sell copies of the Software, and to permit persons to whom the 9a649c2abSJani Nikula * Software is furnished to do so, subject to the following conditions: 10a649c2abSJani Nikula * 11a649c2abSJani Nikula * The above copyright notice and this permission notice (including the next 12a649c2abSJani Nikula * paragraph) shall be included in all copies or substantial portions of the 13a649c2abSJani Nikula * Software. 14a649c2abSJani Nikula * 15a649c2abSJani Nikula * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16a649c2abSJani Nikula * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17a649c2abSJani Nikula * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18a649c2abSJani Nikula * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19a649c2abSJani Nikula * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20a649c2abSJani Nikula * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21a649c2abSJani Nikula * DEALINGS IN THE SOFTWARE. 22a649c2abSJani Nikula */ 23a649c2abSJani Nikula 24a649c2abSJani Nikula /** 25a649c2abSJani Nikula * DOC: atomic plane helpers 26a649c2abSJani Nikula * 27a649c2abSJani Nikula * The functions here are used by the atomic plane helper functions to 28a649c2abSJani Nikula * implement legacy plane updates (i.e., drm_plane->update_plane() and 29a649c2abSJani Nikula * drm_plane->disable_plane()). This allows plane updates to use the 30a649c2abSJani Nikula * atomic state infrastructure and perform plane updates as separate 31a649c2abSJani Nikula * prepare/check/commit/cleanup steps. 32a649c2abSJani Nikula */ 33a649c2abSJani Nikula 34a649c2abSJani Nikula #include <linux/dma-fence-chain.h> 35a649c2abSJani Nikula #include <linux/dma-resv.h> 3631d886b6SJocelyn Falempe #include <linux/iosys-map.h> 37a649c2abSJani Nikula 38a649c2abSJani Nikula #include <drm/drm_atomic_helper.h> 39a649c2abSJani Nikula #include <drm/drm_blend.h> 4031d886b6SJocelyn Falempe #include <drm/drm_cache.h> 41a649c2abSJani Nikula #include <drm/drm_damage_helper.h> 42a649c2abSJani Nikula #include <drm/drm_fourcc.h> 43a649c2abSJani Nikula #include <drm/drm_gem.h> 44a649c2abSJani Nikula #include <drm/drm_gem_atomic_helper.h> 4531d886b6SJocelyn Falempe #include <drm/drm_panic.h> 46a649c2abSJani Nikula 47a649c2abSJani Nikula #include "gem/i915_gem_object.h" 48a649c2abSJani Nikula #include "i915_scheduler_types.h" 49a649c2abSJani Nikula #include "i915_vma.h" 50a649c2abSJani Nikula #include "i9xx_plane_regs.h" 5131d886b6SJocelyn Falempe #include "intel_bo.h" 52a649c2abSJani Nikula #include "intel_cdclk.h" 53a649c2abSJani Nikula #include "intel_cursor.h" 54a649c2abSJani Nikula #include "intel_display_rps.h" 55a649c2abSJani Nikula #include "intel_display_trace.h" 56a649c2abSJani Nikula #include "intel_display_types.h" 57a649c2abSJani Nikula #include "intel_fb.h" 58a649c2abSJani Nikula #include "intel_fb_pin.h" 5931d886b6SJocelyn Falempe #include "intel_fbdev.h" 60a649c2abSJani Nikula #include "intel_plane.h" 61a649c2abSJani Nikula #include "skl_scaler.h" 62a649c2abSJani Nikula #include "skl_universal_plane.h" 63a649c2abSJani Nikula #include "skl_watermark.h" 64a649c2abSJani Nikula 65a649c2abSJani Nikula static void intel_plane_state_reset(struct intel_plane_state *plane_state, 66a649c2abSJani Nikula struct intel_plane *plane) 67a649c2abSJani Nikula { 68a649c2abSJani Nikula memset(plane_state, 0, sizeof(*plane_state)); 69a649c2abSJani Nikula 70a649c2abSJani Nikula __drm_atomic_helper_plane_state_reset(&plane_state->uapi, &plane->base); 71a649c2abSJani Nikula 72a649c2abSJani Nikula plane_state->scaler_id = -1; 73a649c2abSJani Nikula } 74a649c2abSJani Nikula 75a649c2abSJani Nikula struct intel_plane *intel_plane_alloc(void) 76a649c2abSJani Nikula { 77a649c2abSJani Nikula struct intel_plane_state *plane_state; 78a649c2abSJani Nikula struct intel_plane *plane; 79a649c2abSJani Nikula 80a649c2abSJani Nikula plane = kzalloc(sizeof(*plane), GFP_KERNEL); 81a649c2abSJani Nikula if (!plane) 82a649c2abSJani Nikula return ERR_PTR(-ENOMEM); 83a649c2abSJani Nikula 84a649c2abSJani Nikula plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); 85a649c2abSJani Nikula if (!plane_state) { 86a649c2abSJani Nikula kfree(plane); 87a649c2abSJani Nikula return ERR_PTR(-ENOMEM); 88a649c2abSJani Nikula } 89a649c2abSJani Nikula 90a649c2abSJani Nikula intel_plane_state_reset(plane_state, plane); 91a649c2abSJani Nikula 92a649c2abSJani Nikula plane->base.state = &plane_state->uapi; 93a649c2abSJani Nikula 94a649c2abSJani Nikula return plane; 95a649c2abSJani Nikula } 96a649c2abSJani Nikula 97a649c2abSJani Nikula void intel_plane_free(struct intel_plane *plane) 98a649c2abSJani Nikula { 99a649c2abSJani Nikula intel_plane_destroy_state(&plane->base, plane->base.state); 100a649c2abSJani Nikula kfree(plane); 101a649c2abSJani Nikula } 102a649c2abSJani Nikula 103a649c2abSJani Nikula /** 104a649c2abSJani Nikula * intel_plane_destroy - destroy a plane 105a649c2abSJani Nikula * @plane: plane to destroy 106a649c2abSJani Nikula * 107a649c2abSJani Nikula * Common destruction function for all types of planes (primary, cursor, 108a649c2abSJani Nikula * sprite). 109a649c2abSJani Nikula */ 110a649c2abSJani Nikula void intel_plane_destroy(struct drm_plane *plane) 111a649c2abSJani Nikula { 112a649c2abSJani Nikula drm_plane_cleanup(plane); 113a649c2abSJani Nikula kfree(to_intel_plane(plane)); 114a649c2abSJani Nikula } 115a649c2abSJani Nikula 116a649c2abSJani Nikula /** 117a649c2abSJani Nikula * intel_plane_duplicate_state - duplicate plane state 118a649c2abSJani Nikula * @plane: drm plane 119a649c2abSJani Nikula * 120a649c2abSJani Nikula * Allocates and returns a copy of the plane state (both common and 121a649c2abSJani Nikula * Intel-specific) for the specified plane. 122a649c2abSJani Nikula * 123a649c2abSJani Nikula * Returns: The newly allocated plane state, or NULL on failure. 124a649c2abSJani Nikula */ 125a649c2abSJani Nikula struct drm_plane_state * 126a649c2abSJani Nikula intel_plane_duplicate_state(struct drm_plane *plane) 127a649c2abSJani Nikula { 128a649c2abSJani Nikula struct intel_plane_state *intel_state; 129a649c2abSJani Nikula 130a649c2abSJani Nikula intel_state = to_intel_plane_state(plane->state); 131a649c2abSJani Nikula intel_state = kmemdup(intel_state, sizeof(*intel_state), GFP_KERNEL); 132a649c2abSJani Nikula 133a649c2abSJani Nikula if (!intel_state) 134a649c2abSJani Nikula return NULL; 135a649c2abSJani Nikula 136a649c2abSJani Nikula __drm_atomic_helper_plane_duplicate_state(plane, &intel_state->uapi); 137a649c2abSJani Nikula 138a649c2abSJani Nikula intel_state->ggtt_vma = NULL; 139a649c2abSJani Nikula intel_state->dpt_vma = NULL; 140a649c2abSJani Nikula intel_state->flags = 0; 141a649c2abSJani Nikula intel_state->damage = DRM_RECT_INIT(0, 0, 0, 0); 142a649c2abSJani Nikula 143a649c2abSJani Nikula /* add reference to fb */ 144a649c2abSJani Nikula if (intel_state->hw.fb) 145a649c2abSJani Nikula drm_framebuffer_get(intel_state->hw.fb); 146a649c2abSJani Nikula 147a649c2abSJani Nikula return &intel_state->uapi; 148a649c2abSJani Nikula } 149a649c2abSJani Nikula 150a649c2abSJani Nikula /** 151a649c2abSJani Nikula * intel_plane_destroy_state - destroy plane state 152a649c2abSJani Nikula * @plane: drm plane 153a649c2abSJani Nikula * @state: state object to destroy 154a649c2abSJani Nikula * 155a649c2abSJani Nikula * Destroys the plane state (both common and Intel-specific) for the 156a649c2abSJani Nikula * specified plane. 157a649c2abSJani Nikula */ 158a649c2abSJani Nikula void 159a649c2abSJani Nikula intel_plane_destroy_state(struct drm_plane *plane, 160a649c2abSJani Nikula struct drm_plane_state *state) 161a649c2abSJani Nikula { 162a649c2abSJani Nikula struct intel_plane_state *plane_state = to_intel_plane_state(state); 163a649c2abSJani Nikula 164a649c2abSJani Nikula drm_WARN_ON(plane->dev, plane_state->ggtt_vma); 165a649c2abSJani Nikula drm_WARN_ON(plane->dev, plane_state->dpt_vma); 166a649c2abSJani Nikula 167a649c2abSJani Nikula __drm_atomic_helper_plane_destroy_state(&plane_state->uapi); 168a649c2abSJani Nikula if (plane_state->hw.fb) 169a649c2abSJani Nikula drm_framebuffer_put(plane_state->hw.fb); 170a649c2abSJani Nikula kfree(plane_state); 171a649c2abSJani Nikula } 172a649c2abSJani Nikula 173a649c2abSJani Nikula bool intel_plane_needs_physical(struct intel_plane *plane) 174a649c2abSJani Nikula { 175a649c2abSJani Nikula struct intel_display *display = to_intel_display(plane); 176a649c2abSJani Nikula 177a649c2abSJani Nikula return plane->id == PLANE_CURSOR && 178a649c2abSJani Nikula DISPLAY_INFO(display)->cursor_needs_physical; 179a649c2abSJani Nikula } 180a649c2abSJani Nikula 181a649c2abSJani Nikula bool intel_plane_can_async_flip(struct intel_plane *plane, u32 format, 182a649c2abSJani Nikula u64 modifier) 183a649c2abSJani Nikula { 184a649c2abSJani Nikula if (intel_format_info_is_yuv_semiplanar(drm_format_info(format), modifier) || 185a649c2abSJani Nikula format == DRM_FORMAT_C8) 186a649c2abSJani Nikula return false; 187a649c2abSJani Nikula 188a649c2abSJani Nikula return plane->can_async_flip && plane->can_async_flip(modifier); 189a649c2abSJani Nikula } 190a649c2abSJani Nikula 191a649c2abSJani Nikula bool intel_plane_format_mod_supported_async(struct drm_plane *plane, 192a649c2abSJani Nikula u32 format, 193a649c2abSJani Nikula u64 modifier) 194a649c2abSJani Nikula { 195a649c2abSJani Nikula if (!plane->funcs->format_mod_supported(plane, format, modifier)) 196a649c2abSJani Nikula return false; 197a649c2abSJani Nikula 198a649c2abSJani Nikula return intel_plane_can_async_flip(to_intel_plane(plane), 199a649c2abSJani Nikula format, modifier); 200a649c2abSJani Nikula } 201a649c2abSJani Nikula 202a649c2abSJani Nikula unsigned int intel_adjusted_rate(const struct drm_rect *src, 203a649c2abSJani Nikula const struct drm_rect *dst, 204a649c2abSJani Nikula unsigned int rate) 205a649c2abSJani Nikula { 206a649c2abSJani Nikula unsigned int src_w, src_h, dst_w, dst_h; 207a649c2abSJani Nikula 208a649c2abSJani Nikula src_w = drm_rect_width(src) >> 16; 209a649c2abSJani Nikula src_h = drm_rect_height(src) >> 16; 210a649c2abSJani Nikula dst_w = drm_rect_width(dst); 211a649c2abSJani Nikula dst_h = drm_rect_height(dst); 212a649c2abSJani Nikula 213a649c2abSJani Nikula /* Downscaling limits the maximum pixel rate */ 214a649c2abSJani Nikula dst_w = min(src_w, dst_w); 215a649c2abSJani Nikula dst_h = min(src_h, dst_h); 216a649c2abSJani Nikula 217a649c2abSJani Nikula return DIV_ROUND_UP_ULL(mul_u32_u32(rate, src_w * src_h), 218a649c2abSJani Nikula dst_w * dst_h); 219a649c2abSJani Nikula } 220a649c2abSJani Nikula 221a649c2abSJani Nikula unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state, 222a649c2abSJani Nikula const struct intel_plane_state *plane_state) 223a649c2abSJani Nikula { 224a649c2abSJani Nikula /* 225a649c2abSJani Nikula * Note we don't check for plane visibility here as 226a649c2abSJani Nikula * we want to use this when calculating the cursor 227a649c2abSJani Nikula * watermarks even if the cursor is fully offscreen. 228a649c2abSJani Nikula * That depends on the src/dst rectangles being 229a649c2abSJani Nikula * correctly populated whenever the watermark code 230a649c2abSJani Nikula * considers the cursor to be visible, whether or not 231a649c2abSJani Nikula * it is actually visible. 232a649c2abSJani Nikula * 233a649c2abSJani Nikula * See: intel_wm_plane_visible() and intel_check_cursor() 234a649c2abSJani Nikula */ 235a649c2abSJani Nikula 236a649c2abSJani Nikula return intel_adjusted_rate(&plane_state->uapi.src, 237a649c2abSJani Nikula &plane_state->uapi.dst, 238a649c2abSJani Nikula crtc_state->pixel_rate); 239a649c2abSJani Nikula } 240a649c2abSJani Nikula 241a649c2abSJani Nikula unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, 242a649c2abSJani Nikula const struct intel_plane_state *plane_state, 243a649c2abSJani Nikula int color_plane) 244a649c2abSJani Nikula { 245a649c2abSJani Nikula const struct drm_framebuffer *fb = plane_state->hw.fb; 246a649c2abSJani Nikula 247a649c2abSJani Nikula if (!plane_state->uapi.visible) 248a649c2abSJani Nikula return 0; 249a649c2abSJani Nikula 250a649c2abSJani Nikula return intel_plane_pixel_rate(crtc_state, plane_state) * 251a649c2abSJani Nikula fb->format->cpp[color_plane]; 252a649c2abSJani Nikula } 253a649c2abSJani Nikula 254a649c2abSJani Nikula static unsigned int 255a649c2abSJani Nikula intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, 256a649c2abSJani Nikula const struct intel_plane_state *plane_state, 257a649c2abSJani Nikula int color_plane) 258a649c2abSJani Nikula { 259a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 260a649c2abSJani Nikula const struct drm_framebuffer *fb = plane_state->hw.fb; 261a649c2abSJani Nikula unsigned int rel_data_rate; 262a649c2abSJani Nikula int width, height; 263a649c2abSJani Nikula 264a649c2abSJani Nikula if (plane->id == PLANE_CURSOR) 265a649c2abSJani Nikula return 0; 266a649c2abSJani Nikula 267a649c2abSJani Nikula if (!plane_state->uapi.visible) 268a649c2abSJani Nikula return 0; 269a649c2abSJani Nikula 270a649c2abSJani Nikula /* 271a649c2abSJani Nikula * Src coordinates are already rotated by 270 degrees for 272a649c2abSJani Nikula * the 90/270 degree plane rotation cases (to match the 273a649c2abSJani Nikula * GTT mapping), hence no need to account for rotation here. 274a649c2abSJani Nikula */ 275a649c2abSJani Nikula width = drm_rect_width(&plane_state->uapi.src) >> 16; 276a649c2abSJani Nikula height = drm_rect_height(&plane_state->uapi.src) >> 16; 277a649c2abSJani Nikula 278a649c2abSJani Nikula /* UV plane does 1/2 pixel sub-sampling */ 279a649c2abSJani Nikula if (color_plane == 1) { 280a649c2abSJani Nikula width /= 2; 281a649c2abSJani Nikula height /= 2; 282a649c2abSJani Nikula } 283a649c2abSJani Nikula 284a649c2abSJani Nikula rel_data_rate = 285a649c2abSJani Nikula skl_plane_relative_data_rate(crtc_state, plane, width, height, 286a649c2abSJani Nikula fb->format->cpp[color_plane]); 287a649c2abSJani Nikula if (!rel_data_rate) 288a649c2abSJani Nikula return 0; 289a649c2abSJani Nikula 290a649c2abSJani Nikula return intel_adjusted_rate(&plane_state->uapi.src, 291a649c2abSJani Nikula &plane_state->uapi.dst, 292a649c2abSJani Nikula rel_data_rate); 293a649c2abSJani Nikula } 294a649c2abSJani Nikula 295a649c2abSJani Nikula int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, 296a649c2abSJani Nikula struct intel_plane *plane, 297a649c2abSJani Nikula bool *need_cdclk_calc) 298a649c2abSJani Nikula { 299a649c2abSJani Nikula struct intel_display *display = to_intel_display(plane); 300a649c2abSJani Nikula const struct intel_plane_state *plane_state = 301a649c2abSJani Nikula intel_atomic_get_new_plane_state(state, plane); 302a649c2abSJani Nikula struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); 303a649c2abSJani Nikula const struct intel_cdclk_state *cdclk_state; 304a649c2abSJani Nikula const struct intel_crtc_state *old_crtc_state; 305a649c2abSJani Nikula struct intel_crtc_state *new_crtc_state; 306a649c2abSJani Nikula 307a649c2abSJani Nikula if (!plane_state->uapi.visible || !plane->min_cdclk) 308a649c2abSJani Nikula return 0; 309a649c2abSJani Nikula 310a649c2abSJani Nikula old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); 311a649c2abSJani Nikula new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); 312a649c2abSJani Nikula 313a649c2abSJani Nikula new_crtc_state->min_cdclk[plane->id] = 314a649c2abSJani Nikula plane->min_cdclk(new_crtc_state, plane_state); 315a649c2abSJani Nikula 316a649c2abSJani Nikula /* 317a649c2abSJani Nikula * No need to check against the cdclk state if 318a649c2abSJani Nikula * the min cdclk for the plane doesn't increase. 319a649c2abSJani Nikula * 320a649c2abSJani Nikula * Ie. we only ever increase the cdclk due to plane 321a649c2abSJani Nikula * requirements. This can reduce back and forth 322a649c2abSJani Nikula * display blinking due to constant cdclk changes. 323a649c2abSJani Nikula */ 324a649c2abSJani Nikula if (new_crtc_state->min_cdclk[plane->id] <= 325a649c2abSJani Nikula old_crtc_state->min_cdclk[plane->id]) 326a649c2abSJani Nikula return 0; 327a649c2abSJani Nikula 328a649c2abSJani Nikula cdclk_state = intel_atomic_get_cdclk_state(state); 329a649c2abSJani Nikula if (IS_ERR(cdclk_state)) 330a649c2abSJani Nikula return PTR_ERR(cdclk_state); 331a649c2abSJani Nikula 332a649c2abSJani Nikula /* 333a649c2abSJani Nikula * No need to recalculate the cdclk state if 334a649c2abSJani Nikula * the min cdclk for the pipe doesn't increase. 335a649c2abSJani Nikula * 336a649c2abSJani Nikula * Ie. we only ever increase the cdclk due to plane 337a649c2abSJani Nikula * requirements. This can reduce back and forth 338a649c2abSJani Nikula * display blinking due to constant cdclk changes. 339a649c2abSJani Nikula */ 340a649c2abSJani Nikula if (new_crtc_state->min_cdclk[plane->id] <= 341d93ea1d8SJani Nikula intel_cdclk_min_cdclk(cdclk_state, crtc->pipe)) 342a649c2abSJani Nikula return 0; 343a649c2abSJani Nikula 344a649c2abSJani Nikula drm_dbg_kms(display->drm, 345a649c2abSJani Nikula "[PLANE:%d:%s] min cdclk (%d kHz) > [CRTC:%d:%s] min cdclk (%d kHz)\n", 346a649c2abSJani Nikula plane->base.base.id, plane->base.name, 347a649c2abSJani Nikula new_crtc_state->min_cdclk[plane->id], 348a649c2abSJani Nikula crtc->base.base.id, crtc->base.name, 349d93ea1d8SJani Nikula intel_cdclk_min_cdclk(cdclk_state, crtc->pipe)); 350a649c2abSJani Nikula *need_cdclk_calc = true; 351a649c2abSJani Nikula 352a649c2abSJani Nikula return 0; 353a649c2abSJani Nikula } 354a649c2abSJani Nikula 355a649c2abSJani Nikula static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state) 356a649c2abSJani Nikula { 357a649c2abSJani Nikula if (plane_state->hw.fb) 358a649c2abSJani Nikula drm_framebuffer_put(plane_state->hw.fb); 359a649c2abSJani Nikula 360a649c2abSJani Nikula memset(&plane_state->hw, 0, sizeof(plane_state->hw)); 361a649c2abSJani Nikula } 362a649c2abSJani Nikula 363a649c2abSJani Nikula static void 364a649c2abSJani Nikula intel_plane_copy_uapi_plane_damage(struct intel_plane_state *new_plane_state, 365a649c2abSJani Nikula const struct intel_plane_state *old_uapi_plane_state, 366a649c2abSJani Nikula const struct intel_plane_state *new_uapi_plane_state) 367a649c2abSJani Nikula { 368a649c2abSJani Nikula struct intel_display *display = to_intel_display(new_plane_state); 369a649c2abSJani Nikula struct drm_rect *damage = &new_plane_state->damage; 370a649c2abSJani Nikula 371a649c2abSJani Nikula /* damage property tracking enabled from display version 12 onwards */ 372a649c2abSJani Nikula if (DISPLAY_VER(display) < 12) 373a649c2abSJani Nikula return; 374a649c2abSJani Nikula 375a649c2abSJani Nikula if (!drm_atomic_helper_damage_merged(&old_uapi_plane_state->uapi, 376a649c2abSJani Nikula &new_uapi_plane_state->uapi, 377a649c2abSJani Nikula damage)) 378a649c2abSJani Nikula /* Incase helper fails, mark whole plane region as damage */ 379a649c2abSJani Nikula *damage = drm_plane_state_src(&new_uapi_plane_state->uapi); 380a649c2abSJani Nikula } 381a649c2abSJani Nikula 382a649c2abSJani Nikula void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, 383a649c2abSJani Nikula const struct intel_plane_state *from_plane_state, 384a649c2abSJani Nikula struct intel_crtc *crtc) 385a649c2abSJani Nikula { 386a649c2abSJani Nikula intel_plane_clear_hw_state(plane_state); 387a649c2abSJani Nikula 388a649c2abSJani Nikula /* 389a649c2abSJani Nikula * For the joiner secondary uapi.crtc will point at 390a649c2abSJani Nikula * the primary crtc. So we explicitly assign the right 391a649c2abSJani Nikula * secondary crtc to hw.crtc. uapi.crtc!=NULL simply 392a649c2abSJani Nikula * indicates the plane is logically enabled on the uapi level. 393a649c2abSJani Nikula */ 394a649c2abSJani Nikula plane_state->hw.crtc = from_plane_state->uapi.crtc ? &crtc->base : NULL; 395a649c2abSJani Nikula 396a649c2abSJani Nikula plane_state->hw.fb = from_plane_state->uapi.fb; 397a649c2abSJani Nikula if (plane_state->hw.fb) 398a649c2abSJani Nikula drm_framebuffer_get(plane_state->hw.fb); 399a649c2abSJani Nikula 400a649c2abSJani Nikula plane_state->hw.alpha = from_plane_state->uapi.alpha; 401a649c2abSJani Nikula plane_state->hw.pixel_blend_mode = 402a649c2abSJani Nikula from_plane_state->uapi.pixel_blend_mode; 403a649c2abSJani Nikula plane_state->hw.rotation = from_plane_state->uapi.rotation; 404a649c2abSJani Nikula plane_state->hw.color_encoding = from_plane_state->uapi.color_encoding; 405a649c2abSJani Nikula plane_state->hw.color_range = from_plane_state->uapi.color_range; 406a649c2abSJani Nikula plane_state->hw.scaling_filter = from_plane_state->uapi.scaling_filter; 407a649c2abSJani Nikula 408a649c2abSJani Nikula plane_state->uapi.src = drm_plane_state_src(&from_plane_state->uapi); 409a649c2abSJani Nikula plane_state->uapi.dst = drm_plane_state_dest(&from_plane_state->uapi); 410a649c2abSJani Nikula } 411a649c2abSJani Nikula 412a649c2abSJani Nikula void intel_plane_copy_hw_state(struct intel_plane_state *plane_state, 413a649c2abSJani Nikula const struct intel_plane_state *from_plane_state) 414a649c2abSJani Nikula { 415a649c2abSJani Nikula intel_plane_clear_hw_state(plane_state); 416a649c2abSJani Nikula 417a649c2abSJani Nikula memcpy(&plane_state->hw, &from_plane_state->hw, 418a649c2abSJani Nikula sizeof(plane_state->hw)); 419a649c2abSJani Nikula 420a649c2abSJani Nikula if (plane_state->hw.fb) 421a649c2abSJani Nikula drm_framebuffer_get(plane_state->hw.fb); 422a649c2abSJani Nikula } 423a649c2abSJani Nikula 424a649c2abSJani Nikula void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, 425a649c2abSJani Nikula struct intel_plane_state *plane_state) 426a649c2abSJani Nikula { 427a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 428a649c2abSJani Nikula 429a649c2abSJani Nikula crtc_state->active_planes &= ~BIT(plane->id); 430a649c2abSJani Nikula crtc_state->scaled_planes &= ~BIT(plane->id); 431a649c2abSJani Nikula crtc_state->nv12_planes &= ~BIT(plane->id); 432a649c2abSJani Nikula crtc_state->c8_planes &= ~BIT(plane->id); 433a649c2abSJani Nikula crtc_state->async_flip_planes &= ~BIT(plane->id); 434a649c2abSJani Nikula crtc_state->data_rate[plane->id] = 0; 435a649c2abSJani Nikula crtc_state->data_rate_y[plane->id] = 0; 436a649c2abSJani Nikula crtc_state->rel_data_rate[plane->id] = 0; 437a649c2abSJani Nikula crtc_state->rel_data_rate_y[plane->id] = 0; 438a649c2abSJani Nikula crtc_state->min_cdclk[plane->id] = 0; 439a649c2abSJani Nikula 440a649c2abSJani Nikula plane_state->uapi.visible = false; 441a649c2abSJani Nikula } 442a649c2abSJani Nikula 443a649c2abSJani Nikula static bool intel_plane_is_scaled(const struct intel_plane_state *plane_state) 444a649c2abSJani Nikula { 445a649c2abSJani Nikula int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 446a649c2abSJani Nikula int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 447a649c2abSJani Nikula int dst_w = drm_rect_width(&plane_state->uapi.dst); 448a649c2abSJani Nikula int dst_h = drm_rect_height(&plane_state->uapi.dst); 449a649c2abSJani Nikula 450a649c2abSJani Nikula return src_w != dst_w || src_h != dst_h; 451a649c2abSJani Nikula } 452a649c2abSJani Nikula 453a649c2abSJani Nikula static bool intel_plane_do_async_flip(struct intel_plane *plane, 454a649c2abSJani Nikula const struct intel_crtc_state *old_crtc_state, 455a649c2abSJani Nikula const struct intel_crtc_state *new_crtc_state) 456a649c2abSJani Nikula { 457a649c2abSJani Nikula struct intel_display *display = to_intel_display(plane); 458a649c2abSJani Nikula 459a649c2abSJani Nikula if (!plane->async_flip) 460a649c2abSJani Nikula return false; 461a649c2abSJani Nikula 462a649c2abSJani Nikula if (!new_crtc_state->uapi.async_flip) 463a649c2abSJani Nikula return false; 464a649c2abSJani Nikula 465a649c2abSJani Nikula /* 466a649c2abSJani Nikula * In platforms after DISPLAY13, we might need to override 467a649c2abSJani Nikula * first async flip in order to change watermark levels 468a649c2abSJani Nikula * as part of optimization. 469a649c2abSJani Nikula * 470a649c2abSJani Nikula * And let's do this for all skl+ so that we can eg. change the 471a649c2abSJani Nikula * modifier as well. 472a649c2abSJani Nikula * 473a649c2abSJani Nikula * TODO: For older platforms there is less reason to do this as 474a649c2abSJani Nikula * only X-tile is supported with async flips, though we could 475a649c2abSJani Nikula * extend this so other scanout parameters (stride/etc) could 476a649c2abSJani Nikula * be changed as well... 477a649c2abSJani Nikula */ 478a649c2abSJani Nikula return DISPLAY_VER(display) < 9 || old_crtc_state->uapi.async_flip; 479a649c2abSJani Nikula } 480a649c2abSJani Nikula 481a649c2abSJani Nikula static bool i9xx_must_disable_cxsr(const struct intel_crtc_state *new_crtc_state, 482a649c2abSJani Nikula const struct intel_plane_state *old_plane_state, 483a649c2abSJani Nikula const struct intel_plane_state *new_plane_state) 484a649c2abSJani Nikula { 485a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); 486a649c2abSJani Nikula bool old_visible = old_plane_state->uapi.visible; 487a649c2abSJani Nikula bool new_visible = new_plane_state->uapi.visible; 488a649c2abSJani Nikula u32 old_ctl = old_plane_state->ctl; 489a649c2abSJani Nikula u32 new_ctl = new_plane_state->ctl; 490a649c2abSJani Nikula bool modeset, turn_on, turn_off; 491a649c2abSJani Nikula 492a649c2abSJani Nikula if (plane->id == PLANE_CURSOR) 493a649c2abSJani Nikula return false; 494a649c2abSJani Nikula 495a649c2abSJani Nikula modeset = intel_crtc_needs_modeset(new_crtc_state); 496a649c2abSJani Nikula turn_off = old_visible && (!new_visible || modeset); 497a649c2abSJani Nikula turn_on = new_visible && (!old_visible || modeset); 498a649c2abSJani Nikula 499a649c2abSJani Nikula /* Must disable CxSR around plane enable/disable */ 500a649c2abSJani Nikula if (turn_on || turn_off) 501a649c2abSJani Nikula return true; 502a649c2abSJani Nikula 503a649c2abSJani Nikula if (!old_visible || !new_visible) 504a649c2abSJani Nikula return false; 505a649c2abSJani Nikula 506a649c2abSJani Nikula /* 507a649c2abSJani Nikula * Most plane control register updates are blocked while in CxSR. 508a649c2abSJani Nikula * 509a649c2abSJani Nikula * Tiling mode is one exception where the primary plane can 510a649c2abSJani Nikula * apparently handle it, whereas the sprites can not (the 511a649c2abSJani Nikula * sprite issue being only relevant on VLV/CHV where CxSR 512a649c2abSJani Nikula * is actually possible with a sprite enabled). 513a649c2abSJani Nikula */ 514a649c2abSJani Nikula if (plane->id == PLANE_PRIMARY) { 515a649c2abSJani Nikula old_ctl &= ~DISP_TILED; 516a649c2abSJani Nikula new_ctl &= ~DISP_TILED; 517a649c2abSJani Nikula } 518a649c2abSJani Nikula 519a649c2abSJani Nikula return old_ctl != new_ctl; 520a649c2abSJani Nikula } 521a649c2abSJani Nikula 522a649c2abSJani Nikula static bool ilk_must_disable_cxsr(const struct intel_crtc_state *new_crtc_state, 523a649c2abSJani Nikula const struct intel_plane_state *old_plane_state, 524a649c2abSJani Nikula const struct intel_plane_state *new_plane_state) 525a649c2abSJani Nikula { 526a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); 527a649c2abSJani Nikula bool old_visible = old_plane_state->uapi.visible; 528a649c2abSJani Nikula bool new_visible = new_plane_state->uapi.visible; 529a649c2abSJani Nikula bool modeset, turn_on; 530a649c2abSJani Nikula 531a649c2abSJani Nikula if (plane->id == PLANE_CURSOR) 532a649c2abSJani Nikula return false; 533a649c2abSJani Nikula 534a649c2abSJani Nikula modeset = intel_crtc_needs_modeset(new_crtc_state); 535a649c2abSJani Nikula turn_on = new_visible && (!old_visible || modeset); 536a649c2abSJani Nikula 537a649c2abSJani Nikula /* 538a649c2abSJani Nikula * ILK/SNB DVSACNTR/Sprite Enable 539a649c2abSJani Nikula * IVB SPR_CTL/Sprite Enable 540a649c2abSJani Nikula * "When in Self Refresh Big FIFO mode, a write to enable the 541a649c2abSJani Nikula * plane will be internally buffered and delayed while Big FIFO 542a649c2abSJani Nikula * mode is exiting." 543a649c2abSJani Nikula * 544a649c2abSJani Nikula * Which means that enabling the sprite can take an extra frame 545a649c2abSJani Nikula * when we start in big FIFO mode (LP1+). Thus we need to drop 546a649c2abSJani Nikula * down to LP0 and wait for vblank in order to make sure the 547a649c2abSJani Nikula * sprite gets enabled on the next vblank after the register write. 548a649c2abSJani Nikula * Doing otherwise would risk enabling the sprite one frame after 549a649c2abSJani Nikula * we've already signalled flip completion. We can resume LP1+ 550a649c2abSJani Nikula * once the sprite has been enabled. 551a649c2abSJani Nikula * 552a649c2abSJani Nikula * With experimental results seems this is needed also for primary 553a649c2abSJani Nikula * plane, not only sprite plane. 554a649c2abSJani Nikula */ 555a649c2abSJani Nikula if (turn_on) 556a649c2abSJani Nikula return true; 557a649c2abSJani Nikula 558a649c2abSJani Nikula /* 559a649c2abSJani Nikula * WaCxSRDisabledForSpriteScaling:ivb 560a649c2abSJani Nikula * IVB SPR_SCALE/Scaling Enable 561a649c2abSJani Nikula * "Low Power watermarks must be disabled for at least one 562a649c2abSJani Nikula * frame before enabling sprite scaling, and kept disabled 563a649c2abSJani Nikula * until sprite scaling is disabled." 564a649c2abSJani Nikula * 565a649c2abSJani Nikula * ILK/SNB DVSASCALE/Scaling Enable 566a649c2abSJani Nikula * "When in Self Refresh Big FIFO mode, scaling enable will be 567a649c2abSJani Nikula * masked off while Big FIFO mode is exiting." 568a649c2abSJani Nikula * 569a649c2abSJani Nikula * Despite the w/a only being listed for IVB we assume that 570a649c2abSJani Nikula * the ILK/SNB note has similar ramifications, hence we apply 571a649c2abSJani Nikula * the w/a on all three platforms. 572a649c2abSJani Nikula */ 573a649c2abSJani Nikula return !intel_plane_is_scaled(old_plane_state) && 574a649c2abSJani Nikula intel_plane_is_scaled(new_plane_state); 575a649c2abSJani Nikula } 576a649c2abSJani Nikula 577a649c2abSJani Nikula static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state, 578a649c2abSJani Nikula struct intel_crtc_state *new_crtc_state, 579a649c2abSJani Nikula const struct intel_plane_state *old_plane_state, 580a649c2abSJani Nikula struct intel_plane_state *new_plane_state) 581a649c2abSJani Nikula { 582a649c2abSJani Nikula struct intel_display *display = to_intel_display(new_crtc_state); 583a649c2abSJani Nikula struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); 584a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); 585a649c2abSJani Nikula bool mode_changed = intel_crtc_needs_modeset(new_crtc_state); 586a649c2abSJani Nikula bool was_crtc_enabled = old_crtc_state->hw.active; 587a649c2abSJani Nikula bool is_crtc_enabled = new_crtc_state->hw.active; 588a649c2abSJani Nikula bool turn_off, turn_on, visible, was_visible; 589a649c2abSJani Nikula int ret; 590a649c2abSJani Nikula 591a649c2abSJani Nikula if (DISPLAY_VER(display) >= 9 && plane->id != PLANE_CURSOR) { 592a649c2abSJani Nikula ret = skl_update_scaler_plane(new_crtc_state, new_plane_state); 593a649c2abSJani Nikula if (ret) 594a649c2abSJani Nikula return ret; 595a649c2abSJani Nikula } 596a649c2abSJani Nikula 597a649c2abSJani Nikula was_visible = old_plane_state->uapi.visible; 598a649c2abSJani Nikula visible = new_plane_state->uapi.visible; 599a649c2abSJani Nikula 600a649c2abSJani Nikula if (!was_crtc_enabled && drm_WARN_ON(display->drm, was_visible)) 601a649c2abSJani Nikula was_visible = false; 602a649c2abSJani Nikula 603a649c2abSJani Nikula /* 604a649c2abSJani Nikula * Visibility is calculated as if the crtc was on, but 605a649c2abSJani Nikula * after scaler setup everything depends on it being off 606a649c2abSJani Nikula * when the crtc isn't active. 607a649c2abSJani Nikula * 608a649c2abSJani Nikula * FIXME this is wrong for watermarks. Watermarks should also 609a649c2abSJani Nikula * be computed as if the pipe would be active. Perhaps move 610a649c2abSJani Nikula * per-plane wm computation to the .check_plane() hook, and 611a649c2abSJani Nikula * only combine the results from all planes in the current place? 612a649c2abSJani Nikula */ 613a649c2abSJani Nikula if (!is_crtc_enabled) { 614a649c2abSJani Nikula intel_plane_set_invisible(new_crtc_state, new_plane_state); 615a649c2abSJani Nikula visible = false; 616a649c2abSJani Nikula } 617a649c2abSJani Nikula 618a649c2abSJani Nikula if (!was_visible && !visible) 619a649c2abSJani Nikula return 0; 620a649c2abSJani Nikula 621a649c2abSJani Nikula turn_off = was_visible && (!visible || mode_changed); 622a649c2abSJani Nikula turn_on = visible && (!was_visible || mode_changed); 623a649c2abSJani Nikula 624a649c2abSJani Nikula drm_dbg_atomic(display->drm, 625a649c2abSJani Nikula "[CRTC:%d:%s] with [PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n", 626a649c2abSJani Nikula crtc->base.base.id, crtc->base.name, 627a649c2abSJani Nikula plane->base.base.id, plane->base.name, 628a649c2abSJani Nikula was_visible, visible, 629a649c2abSJani Nikula turn_off, turn_on, mode_changed); 630a649c2abSJani Nikula 631a649c2abSJani Nikula if (visible || was_visible) 632a649c2abSJani Nikula new_crtc_state->fb_bits |= plane->frontbuffer_bit; 633a649c2abSJani Nikula 634a649c2abSJani Nikula if (HAS_GMCH(display) && 635a649c2abSJani Nikula i9xx_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state)) 636a649c2abSJani Nikula new_crtc_state->disable_cxsr = true; 637a649c2abSJani Nikula 638a649c2abSJani Nikula if ((display->platform.ironlake || display->platform.sandybridge || display->platform.ivybridge) && 639a649c2abSJani Nikula ilk_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state)) 640a649c2abSJani Nikula new_crtc_state->disable_cxsr = true; 641a649c2abSJani Nikula 642a649c2abSJani Nikula if (intel_plane_do_async_flip(plane, old_crtc_state, new_crtc_state)) { 643a649c2abSJani Nikula new_crtc_state->do_async_flip = true; 644a649c2abSJani Nikula new_crtc_state->async_flip_planes |= BIT(plane->id); 645a649c2abSJani Nikula } else if (plane->need_async_flip_toggle_wa && 646a649c2abSJani Nikula new_crtc_state->uapi.async_flip) { 647a649c2abSJani Nikula /* 648a649c2abSJani Nikula * On platforms with double buffered async flip bit we 649a649c2abSJani Nikula * set the bit already one frame early during the sync 650a649c2abSJani Nikula * flip (see {i9xx,skl}_plane_update_arm()). The 651a649c2abSJani Nikula * hardware will therefore be ready to perform a real 652a649c2abSJani Nikula * async flip during the next commit, without having 653a649c2abSJani Nikula * to wait yet another frame for the bit to latch. 654a649c2abSJani Nikula */ 655a649c2abSJani Nikula new_crtc_state->async_flip_planes |= BIT(plane->id); 656a649c2abSJani Nikula } 657a649c2abSJani Nikula 658a649c2abSJani Nikula return 0; 659a649c2abSJani Nikula } 660a649c2abSJani Nikula 661a649c2abSJani Nikula int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state, 662a649c2abSJani Nikula struct intel_crtc_state *new_crtc_state, 663a649c2abSJani Nikula const struct intel_plane_state *old_plane_state, 664a649c2abSJani Nikula struct intel_plane_state *new_plane_state) 665a649c2abSJani Nikula { 666a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); 667a649c2abSJani Nikula const struct drm_framebuffer *fb = new_plane_state->hw.fb; 668a649c2abSJani Nikula int ret; 669a649c2abSJani Nikula 670a649c2abSJani Nikula intel_plane_set_invisible(new_crtc_state, new_plane_state); 671a649c2abSJani Nikula new_crtc_state->enabled_planes &= ~BIT(plane->id); 672a649c2abSJani Nikula 673a649c2abSJani Nikula if (!new_plane_state->hw.crtc && !old_plane_state->hw.crtc) 674a649c2abSJani Nikula return 0; 675a649c2abSJani Nikula 676a649c2abSJani Nikula ret = plane->check_plane(new_crtc_state, new_plane_state); 677a649c2abSJani Nikula if (ret) 678a649c2abSJani Nikula return ret; 679a649c2abSJani Nikula 680a649c2abSJani Nikula if (fb) 681a649c2abSJani Nikula new_crtc_state->enabled_planes |= BIT(plane->id); 682a649c2abSJani Nikula 683a649c2abSJani Nikula /* FIXME pre-g4x don't work like this */ 684a649c2abSJani Nikula if (new_plane_state->uapi.visible) 685a649c2abSJani Nikula new_crtc_state->active_planes |= BIT(plane->id); 686a649c2abSJani Nikula 687a649c2abSJani Nikula if (new_plane_state->uapi.visible && 688a649c2abSJani Nikula intel_plane_is_scaled(new_plane_state)) 689a649c2abSJani Nikula new_crtc_state->scaled_planes |= BIT(plane->id); 690a649c2abSJani Nikula 691a649c2abSJani Nikula if (new_plane_state->uapi.visible && 692a649c2abSJani Nikula intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) 693a649c2abSJani Nikula new_crtc_state->nv12_planes |= BIT(plane->id); 694a649c2abSJani Nikula 695a649c2abSJani Nikula if (new_plane_state->uapi.visible && 696a649c2abSJani Nikula fb->format->format == DRM_FORMAT_C8) 697a649c2abSJani Nikula new_crtc_state->c8_planes |= BIT(plane->id); 698a649c2abSJani Nikula 699a649c2abSJani Nikula if (new_plane_state->uapi.visible || old_plane_state->uapi.visible) 700a649c2abSJani Nikula new_crtc_state->update_planes |= BIT(plane->id); 701a649c2abSJani Nikula 702a649c2abSJani Nikula if (new_plane_state->uapi.visible && 703a649c2abSJani Nikula intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { 704a649c2abSJani Nikula new_crtc_state->data_rate_y[plane->id] = 705a649c2abSJani Nikula intel_plane_data_rate(new_crtc_state, new_plane_state, 0); 706a649c2abSJani Nikula new_crtc_state->data_rate[plane->id] = 707a649c2abSJani Nikula intel_plane_data_rate(new_crtc_state, new_plane_state, 1); 708a649c2abSJani Nikula 709a649c2abSJani Nikula new_crtc_state->rel_data_rate_y[plane->id] = 710a649c2abSJani Nikula intel_plane_relative_data_rate(new_crtc_state, 711a649c2abSJani Nikula new_plane_state, 0); 712a649c2abSJani Nikula new_crtc_state->rel_data_rate[plane->id] = 713a649c2abSJani Nikula intel_plane_relative_data_rate(new_crtc_state, 714a649c2abSJani Nikula new_plane_state, 1); 715a649c2abSJani Nikula } else if (new_plane_state->uapi.visible) { 716a649c2abSJani Nikula new_crtc_state->data_rate[plane->id] = 717a649c2abSJani Nikula intel_plane_data_rate(new_crtc_state, new_plane_state, 0); 718a649c2abSJani Nikula 719a649c2abSJani Nikula new_crtc_state->rel_data_rate[plane->id] = 720a649c2abSJani Nikula intel_plane_relative_data_rate(new_crtc_state, 721a649c2abSJani Nikula new_plane_state, 0); 722a649c2abSJani Nikula } 723a649c2abSJani Nikula 724a649c2abSJani Nikula return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state, 725a649c2abSJani Nikula old_plane_state, new_plane_state); 726a649c2abSJani Nikula } 727a649c2abSJani Nikula 728a649c2abSJani Nikula struct intel_plane * 729a649c2abSJani Nikula intel_crtc_get_plane(struct intel_crtc *crtc, enum plane_id plane_id) 730a649c2abSJani Nikula { 731a649c2abSJani Nikula struct intel_display *display = to_intel_display(crtc); 732a649c2abSJani Nikula struct intel_plane *plane; 733a649c2abSJani Nikula 734a649c2abSJani Nikula for_each_intel_plane_on_crtc(display->drm, crtc, plane) { 735a649c2abSJani Nikula if (plane->id == plane_id) 736a649c2abSJani Nikula return plane; 737a649c2abSJani Nikula } 738a649c2abSJani Nikula 739a649c2abSJani Nikula return NULL; 740a649c2abSJani Nikula } 741a649c2abSJani Nikula 74251c2590dSJani Nikula static int plane_atomic_check(struct intel_atomic_state *state, 743a649c2abSJani Nikula struct intel_plane *plane) 744a649c2abSJani Nikula { 745a649c2abSJani Nikula struct intel_display *display = to_intel_display(state); 746a649c2abSJani Nikula struct intel_plane_state *new_plane_state = 747a649c2abSJani Nikula intel_atomic_get_new_plane_state(state, plane); 748a649c2abSJani Nikula const struct intel_plane_state *old_plane_state = 749a649c2abSJani Nikula intel_atomic_get_old_plane_state(state, plane); 750a649c2abSJani Nikula const struct intel_plane_state *new_primary_crtc_plane_state; 751a649c2abSJani Nikula const struct intel_plane_state *old_primary_crtc_plane_state; 752a649c2abSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(display, plane->pipe); 753a649c2abSJani Nikula const struct intel_crtc_state *old_crtc_state = 754a649c2abSJani Nikula intel_atomic_get_old_crtc_state(state, crtc); 755a649c2abSJani Nikula struct intel_crtc_state *new_crtc_state = 756a649c2abSJani Nikula intel_atomic_get_new_crtc_state(state, crtc); 757a649c2abSJani Nikula 758a649c2abSJani Nikula if (new_crtc_state && intel_crtc_is_joiner_secondary(new_crtc_state)) { 759a649c2abSJani Nikula struct intel_crtc *primary_crtc = 760a649c2abSJani Nikula intel_primary_crtc(new_crtc_state); 761a649c2abSJani Nikula struct intel_plane *primary_crtc_plane = 762a649c2abSJani Nikula intel_crtc_get_plane(primary_crtc, plane->id); 763a649c2abSJani Nikula 764a649c2abSJani Nikula new_primary_crtc_plane_state = 765a649c2abSJani Nikula intel_atomic_get_new_plane_state(state, primary_crtc_plane); 766a649c2abSJani Nikula old_primary_crtc_plane_state = 767a649c2abSJani Nikula intel_atomic_get_old_plane_state(state, primary_crtc_plane); 768a649c2abSJani Nikula } else { 769a649c2abSJani Nikula new_primary_crtc_plane_state = new_plane_state; 770a649c2abSJani Nikula old_primary_crtc_plane_state = old_plane_state; 771a649c2abSJani Nikula } 772a649c2abSJani Nikula 773a649c2abSJani Nikula intel_plane_copy_uapi_plane_damage(new_plane_state, 774a649c2abSJani Nikula old_primary_crtc_plane_state, 775a649c2abSJani Nikula new_primary_crtc_plane_state); 776a649c2abSJani Nikula 777a649c2abSJani Nikula intel_plane_copy_uapi_to_hw_state(new_plane_state, 778a649c2abSJani Nikula new_primary_crtc_plane_state, 779a649c2abSJani Nikula crtc); 780a649c2abSJani Nikula 781a649c2abSJani Nikula new_plane_state->uapi.visible = false; 782a649c2abSJani Nikula if (!new_crtc_state) 783a649c2abSJani Nikula return 0; 784a649c2abSJani Nikula 785a649c2abSJani Nikula return intel_plane_atomic_check_with_state(old_crtc_state, 786a649c2abSJani Nikula new_crtc_state, 787a649c2abSJani Nikula old_plane_state, 788a649c2abSJani Nikula new_plane_state); 789a649c2abSJani Nikula } 790a649c2abSJani Nikula 791a649c2abSJani Nikula static struct intel_plane * 792a649c2abSJani Nikula skl_next_plane_to_commit(struct intel_atomic_state *state, 793a649c2abSJani Nikula struct intel_crtc *crtc, 794a649c2abSJani Nikula struct skl_ddb_entry ddb[I915_MAX_PLANES], 795a649c2abSJani Nikula struct skl_ddb_entry ddb_y[I915_MAX_PLANES], 796a649c2abSJani Nikula unsigned int *update_mask) 797a649c2abSJani Nikula { 798a649c2abSJani Nikula struct intel_crtc_state *crtc_state = 799a649c2abSJani Nikula intel_atomic_get_new_crtc_state(state, crtc); 800a649c2abSJani Nikula struct intel_plane_state __maybe_unused *plane_state; 801a649c2abSJani Nikula struct intel_plane *plane; 802a649c2abSJani Nikula int i; 803a649c2abSJani Nikula 804a649c2abSJani Nikula if (*update_mask == 0) 805a649c2abSJani Nikula return NULL; 806a649c2abSJani Nikula 807a649c2abSJani Nikula for_each_new_intel_plane_in_state(state, plane, plane_state, i) { 808a649c2abSJani Nikula enum plane_id plane_id = plane->id; 809a649c2abSJani Nikula 810a649c2abSJani Nikula if (crtc->pipe != plane->pipe || 811a649c2abSJani Nikula !(*update_mask & BIT(plane_id))) 812a649c2abSJani Nikula continue; 813a649c2abSJani Nikula 814a649c2abSJani Nikula if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb[plane_id], 815a649c2abSJani Nikula ddb, I915_MAX_PLANES, plane_id) || 816a649c2abSJani Nikula skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id], 817a649c2abSJani Nikula ddb_y, I915_MAX_PLANES, plane_id)) 818a649c2abSJani Nikula continue; 819a649c2abSJani Nikula 820a649c2abSJani Nikula *update_mask &= ~BIT(plane_id); 821a649c2abSJani Nikula ddb[plane_id] = crtc_state->wm.skl.plane_ddb[plane_id]; 822a649c2abSJani Nikula ddb_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id]; 823a649c2abSJani Nikula 824a649c2abSJani Nikula return plane; 825a649c2abSJani Nikula } 826a649c2abSJani Nikula 827a649c2abSJani Nikula /* should never happen */ 828a649c2abSJani Nikula drm_WARN_ON(state->base.dev, 1); 829a649c2abSJani Nikula 830a649c2abSJani Nikula return NULL; 831a649c2abSJani Nikula } 832a649c2abSJani Nikula 833a649c2abSJani Nikula void intel_plane_update_noarm(struct intel_dsb *dsb, 834a649c2abSJani Nikula struct intel_plane *plane, 835a649c2abSJani Nikula const struct intel_crtc_state *crtc_state, 836a649c2abSJani Nikula const struct intel_plane_state *plane_state) 837a649c2abSJani Nikula { 838a649c2abSJani Nikula struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 839a649c2abSJani Nikula 840a649c2abSJani Nikula trace_intel_plane_update_noarm(plane_state, crtc); 841a649c2abSJani Nikula 842a649c2abSJani Nikula if (plane->fbc) 843a649c2abSJani Nikula intel_fbc_dirty_rect_update_noarm(dsb, plane); 844a649c2abSJani Nikula 845a649c2abSJani Nikula if (plane->update_noarm) 846a649c2abSJani Nikula plane->update_noarm(dsb, plane, crtc_state, plane_state); 847a649c2abSJani Nikula } 848a649c2abSJani Nikula 849a649c2abSJani Nikula void intel_plane_async_flip(struct intel_dsb *dsb, 850a649c2abSJani Nikula struct intel_plane *plane, 851a649c2abSJani Nikula const struct intel_crtc_state *crtc_state, 852a649c2abSJani Nikula const struct intel_plane_state *plane_state, 853a649c2abSJani Nikula bool async_flip) 854a649c2abSJani Nikula { 855a649c2abSJani Nikula struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 856a649c2abSJani Nikula 857a649c2abSJani Nikula trace_intel_plane_async_flip(plane, crtc, async_flip); 858a649c2abSJani Nikula plane->async_flip(dsb, plane, crtc_state, plane_state, async_flip); 859a649c2abSJani Nikula } 860a649c2abSJani Nikula 861a649c2abSJani Nikula void intel_plane_update_arm(struct intel_dsb *dsb, 862a649c2abSJani Nikula struct intel_plane *plane, 863a649c2abSJani Nikula const struct intel_crtc_state *crtc_state, 864a649c2abSJani Nikula const struct intel_plane_state *plane_state) 865a649c2abSJani Nikula { 866a649c2abSJani Nikula struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 867a649c2abSJani Nikula 868a649c2abSJani Nikula if (crtc_state->do_async_flip && plane->async_flip) { 869a649c2abSJani Nikula intel_plane_async_flip(dsb, plane, crtc_state, plane_state, true); 870a649c2abSJani Nikula return; 871a649c2abSJani Nikula } 872a649c2abSJani Nikula 873a649c2abSJani Nikula trace_intel_plane_update_arm(plane_state, crtc); 874a649c2abSJani Nikula plane->update_arm(dsb, plane, crtc_state, plane_state); 875a649c2abSJani Nikula } 876a649c2abSJani Nikula 877a649c2abSJani Nikula void intel_plane_disable_arm(struct intel_dsb *dsb, 878a649c2abSJani Nikula struct intel_plane *plane, 879a649c2abSJani Nikula const struct intel_crtc_state *crtc_state) 880a649c2abSJani Nikula { 881a649c2abSJani Nikula struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 882a649c2abSJani Nikula 883a649c2abSJani Nikula trace_intel_plane_disable_arm(plane, crtc); 884a649c2abSJani Nikula plane->disable_arm(dsb, plane, crtc_state); 885a649c2abSJani Nikula } 886a649c2abSJani Nikula 887a649c2abSJani Nikula void intel_crtc_planes_update_noarm(struct intel_dsb *dsb, 888a649c2abSJani Nikula struct intel_atomic_state *state, 889a649c2abSJani Nikula struct intel_crtc *crtc) 890a649c2abSJani Nikula { 891a649c2abSJani Nikula struct intel_crtc_state *new_crtc_state = 892a649c2abSJani Nikula intel_atomic_get_new_crtc_state(state, crtc); 893a649c2abSJani Nikula u32 update_mask = new_crtc_state->update_planes; 894a649c2abSJani Nikula struct intel_plane_state *new_plane_state; 895a649c2abSJani Nikula struct intel_plane *plane; 896a649c2abSJani Nikula int i; 897a649c2abSJani Nikula 898a649c2abSJani Nikula if (new_crtc_state->do_async_flip) 899a649c2abSJani Nikula return; 900a649c2abSJani Nikula 901a649c2abSJani Nikula /* 902a649c2abSJani Nikula * Since we only write non-arming registers here, 903a649c2abSJani Nikula * the order does not matter even for skl+. 904a649c2abSJani Nikula */ 905a649c2abSJani Nikula for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) { 906a649c2abSJani Nikula if (crtc->pipe != plane->pipe || 907a649c2abSJani Nikula !(update_mask & BIT(plane->id))) 908a649c2abSJani Nikula continue; 909a649c2abSJani Nikula 910a649c2abSJani Nikula /* TODO: for mailbox updates this should be skipped */ 911a649c2abSJani Nikula if (new_plane_state->uapi.visible || 912a649c2abSJani Nikula new_plane_state->is_y_plane) 913a649c2abSJani Nikula intel_plane_update_noarm(dsb, plane, 914a649c2abSJani Nikula new_crtc_state, new_plane_state); 915a649c2abSJani Nikula } 916a649c2abSJani Nikula } 917a649c2abSJani Nikula 918a649c2abSJani Nikula static void skl_crtc_planes_update_arm(struct intel_dsb *dsb, 919a649c2abSJani Nikula struct intel_atomic_state *state, 920a649c2abSJani Nikula struct intel_crtc *crtc) 921a649c2abSJani Nikula { 922a649c2abSJani Nikula struct intel_crtc_state *old_crtc_state = 923a649c2abSJani Nikula intel_atomic_get_old_crtc_state(state, crtc); 924a649c2abSJani Nikula struct intel_crtc_state *new_crtc_state = 925a649c2abSJani Nikula intel_atomic_get_new_crtc_state(state, crtc); 926a649c2abSJani Nikula struct skl_ddb_entry ddb[I915_MAX_PLANES]; 927a649c2abSJani Nikula struct skl_ddb_entry ddb_y[I915_MAX_PLANES]; 928a649c2abSJani Nikula u32 update_mask = new_crtc_state->update_planes; 929a649c2abSJani Nikula struct intel_plane *plane; 930a649c2abSJani Nikula 931a649c2abSJani Nikula memcpy(ddb, old_crtc_state->wm.skl.plane_ddb, 932a649c2abSJani Nikula sizeof(old_crtc_state->wm.skl.plane_ddb)); 933a649c2abSJani Nikula memcpy(ddb_y, old_crtc_state->wm.skl.plane_ddb_y, 934a649c2abSJani Nikula sizeof(old_crtc_state->wm.skl.plane_ddb_y)); 935a649c2abSJani Nikula 936a649c2abSJani Nikula while ((plane = skl_next_plane_to_commit(state, crtc, ddb, ddb_y, &update_mask))) { 937a649c2abSJani Nikula struct intel_plane_state *new_plane_state = 938a649c2abSJani Nikula intel_atomic_get_new_plane_state(state, plane); 939a649c2abSJani Nikula 940a649c2abSJani Nikula /* 941a649c2abSJani Nikula * TODO: for mailbox updates intel_plane_update_noarm() 942a649c2abSJani Nikula * would have to be called here as well. 943a649c2abSJani Nikula */ 944a649c2abSJani Nikula if (new_plane_state->uapi.visible || 945a649c2abSJani Nikula new_plane_state->is_y_plane) 946a649c2abSJani Nikula intel_plane_update_arm(dsb, plane, new_crtc_state, new_plane_state); 947a649c2abSJani Nikula else 948a649c2abSJani Nikula intel_plane_disable_arm(dsb, plane, new_crtc_state); 949a649c2abSJani Nikula } 950a649c2abSJani Nikula } 951a649c2abSJani Nikula 952a649c2abSJani Nikula static void i9xx_crtc_planes_update_arm(struct intel_dsb *dsb, 953a649c2abSJani Nikula struct intel_atomic_state *state, 954a649c2abSJani Nikula struct intel_crtc *crtc) 955a649c2abSJani Nikula { 956a649c2abSJani Nikula struct intel_crtc_state *new_crtc_state = 957a649c2abSJani Nikula intel_atomic_get_new_crtc_state(state, crtc); 958a649c2abSJani Nikula u32 update_mask = new_crtc_state->update_planes; 959a649c2abSJani Nikula struct intel_plane_state *new_plane_state; 960a649c2abSJani Nikula struct intel_plane *plane; 961a649c2abSJani Nikula int i; 962a649c2abSJani Nikula 963a649c2abSJani Nikula for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) { 964a649c2abSJani Nikula if (crtc->pipe != plane->pipe || 965a649c2abSJani Nikula !(update_mask & BIT(plane->id))) 966a649c2abSJani Nikula continue; 967a649c2abSJani Nikula 968a649c2abSJani Nikula /* 969a649c2abSJani Nikula * TODO: for mailbox updates intel_plane_update_noarm() 970a649c2abSJani Nikula * would have to be called here as well. 971a649c2abSJani Nikula */ 972a649c2abSJani Nikula if (new_plane_state->uapi.visible) 973a649c2abSJani Nikula intel_plane_update_arm(dsb, plane, new_crtc_state, new_plane_state); 974a649c2abSJani Nikula else 975a649c2abSJani Nikula intel_plane_disable_arm(dsb, plane, new_crtc_state); 976a649c2abSJani Nikula } 977a649c2abSJani Nikula } 978a649c2abSJani Nikula 979a649c2abSJani Nikula void intel_crtc_planes_update_arm(struct intel_dsb *dsb, 980a649c2abSJani Nikula struct intel_atomic_state *state, 981a649c2abSJani Nikula struct intel_crtc *crtc) 982a649c2abSJani Nikula { 983a649c2abSJani Nikula struct intel_display *display = to_intel_display(state); 984a649c2abSJani Nikula 985a649c2abSJani Nikula if (DISPLAY_VER(display) >= 9) 986a649c2abSJani Nikula skl_crtc_planes_update_arm(dsb, state, crtc); 987a649c2abSJani Nikula else 988a649c2abSJani Nikula i9xx_crtc_planes_update_arm(dsb, state, crtc); 989a649c2abSJani Nikula } 990a649c2abSJani Nikula 99115af755fSJani Nikula int intel_plane_check_clipping(struct intel_plane_state *plane_state, 992a649c2abSJani Nikula struct intel_crtc_state *crtc_state, 993a649c2abSJani Nikula int min_scale, int max_scale, 994a649c2abSJani Nikula bool can_position) 995a649c2abSJani Nikula { 996a649c2abSJani Nikula struct intel_display *display = to_intel_display(plane_state); 997a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 998a649c2abSJani Nikula struct drm_framebuffer *fb = plane_state->hw.fb; 999a649c2abSJani Nikula struct drm_rect *src = &plane_state->uapi.src; 1000a649c2abSJani Nikula struct drm_rect *dst = &plane_state->uapi.dst; 1001a649c2abSJani Nikula const struct drm_rect *clip = &crtc_state->pipe_src; 1002a649c2abSJani Nikula unsigned int rotation = plane_state->hw.rotation; 1003a649c2abSJani Nikula int hscale, vscale; 1004a649c2abSJani Nikula 1005a649c2abSJani Nikula if (!fb) { 1006a649c2abSJani Nikula plane_state->uapi.visible = false; 1007a649c2abSJani Nikula return 0; 1008a649c2abSJani Nikula } 1009a649c2abSJani Nikula 1010a649c2abSJani Nikula drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation); 1011a649c2abSJani Nikula 1012a649c2abSJani Nikula /* Check scaling */ 1013a649c2abSJani Nikula hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); 1014a649c2abSJani Nikula vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); 1015a649c2abSJani Nikula if (hscale < 0 || vscale < 0) { 1016a649c2abSJani Nikula drm_dbg_kms(display->drm, 1017a649c2abSJani Nikula "[PLANE:%d:%s] invalid scaling "DRM_RECT_FP_FMT " -> " DRM_RECT_FMT "\n", 1018a649c2abSJani Nikula plane->base.base.id, plane->base.name, 1019a649c2abSJani Nikula DRM_RECT_FP_ARG(src), DRM_RECT_ARG(dst)); 1020a649c2abSJani Nikula return -ERANGE; 1021a649c2abSJani Nikula } 1022a649c2abSJani Nikula 1023a649c2abSJani Nikula /* 1024a649c2abSJani Nikula * FIXME: This might need further adjustment for seamless scaling 1025a649c2abSJani Nikula * with phase information, for the 2p2 and 2p1 scenarios. 1026a649c2abSJani Nikula */ 1027a649c2abSJani Nikula plane_state->uapi.visible = drm_rect_clip_scaled(src, dst, clip); 1028a649c2abSJani Nikula 1029a649c2abSJani Nikula drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); 1030a649c2abSJani Nikula 1031a649c2abSJani Nikula if (!can_position && plane_state->uapi.visible && 1032a649c2abSJani Nikula !drm_rect_equals(dst, clip)) { 1033a649c2abSJani Nikula drm_dbg_kms(display->drm, 1034a649c2abSJani Nikula "[PLANE:%d:%s] plane (" DRM_RECT_FMT ") must cover entire CRTC (" DRM_RECT_FMT ")\n", 1035a649c2abSJani Nikula plane->base.base.id, plane->base.name, 1036a649c2abSJani Nikula DRM_RECT_ARG(dst), DRM_RECT_ARG(clip)); 1037a649c2abSJani Nikula return -EINVAL; 1038a649c2abSJani Nikula } 1039a649c2abSJani Nikula 1040a649c2abSJani Nikula /* final plane coordinates will be relative to the plane's pipe */ 1041a649c2abSJani Nikula drm_rect_translate(dst, -clip->x1, -clip->y1); 1042a649c2abSJani Nikula 1043a649c2abSJani Nikula return 0; 1044a649c2abSJani Nikula } 1045a649c2abSJani Nikula 1046a649c2abSJani Nikula int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) 1047a649c2abSJani Nikula { 1048a649c2abSJani Nikula struct intel_display *display = to_intel_display(plane_state); 1049a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1050a649c2abSJani Nikula const struct drm_framebuffer *fb = plane_state->hw.fb; 1051a649c2abSJani Nikula struct drm_rect *src = &plane_state->uapi.src; 1052a649c2abSJani Nikula u32 src_x, src_y, src_w, src_h, hsub, vsub; 1053a649c2abSJani Nikula bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation); 1054a649c2abSJani Nikula 1055a649c2abSJani Nikula /* 1056a649c2abSJani Nikula * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS 1057a649c2abSJani Nikula * abuses hsub/vsub so we can't use them here. But as they 1058a649c2abSJani Nikula * are limited to 32bpp RGB formats we don't actually need 1059a649c2abSJani Nikula * to check anything. 1060a649c2abSJani Nikula */ 1061a649c2abSJani Nikula if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || 1062a649c2abSJani Nikula fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS) 1063a649c2abSJani Nikula return 0; 1064a649c2abSJani Nikula 1065a649c2abSJani Nikula /* 1066a649c2abSJani Nikula * Hardware doesn't handle subpixel coordinates. 1067a649c2abSJani Nikula * Adjust to (macro)pixel boundary, but be careful not to 1068a649c2abSJani Nikula * increase the source viewport size, because that could 1069a649c2abSJani Nikula * push the downscaling factor out of bounds. 1070a649c2abSJani Nikula */ 1071a649c2abSJani Nikula src_x = src->x1 >> 16; 1072a649c2abSJani Nikula src_w = drm_rect_width(src) >> 16; 1073a649c2abSJani Nikula src_y = src->y1 >> 16; 1074a649c2abSJani Nikula src_h = drm_rect_height(src) >> 16; 1075a649c2abSJani Nikula 1076a649c2abSJani Nikula drm_rect_init(src, src_x << 16, src_y << 16, 1077a649c2abSJani Nikula src_w << 16, src_h << 16); 1078a649c2abSJani Nikula 1079a649c2abSJani Nikula if (fb->format->format == DRM_FORMAT_RGB565 && rotated) { 1080a649c2abSJani Nikula hsub = 2; 1081a649c2abSJani Nikula vsub = 2; 1082a649c2abSJani Nikula } else if (DISPLAY_VER(display) >= 20 && 1083a649c2abSJani Nikula intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { 1084a649c2abSJani Nikula /* 1085a649c2abSJani Nikula * This allows NV12 and P0xx formats to have odd size and/or odd 1086a649c2abSJani Nikula * source coordinates on DISPLAY_VER(display) >= 20 1087a649c2abSJani Nikula */ 1088a649c2abSJani Nikula hsub = 1; 1089a649c2abSJani Nikula vsub = 1; 1090a649c2abSJani Nikula 1091a649c2abSJani Nikula /* Wa_16023981245 */ 1092a649c2abSJani Nikula if ((DISPLAY_VERx100(display) == 2000 || 1093a649c2abSJani Nikula DISPLAY_VERx100(display) == 3000 || 1094a649c2abSJani Nikula DISPLAY_VERx100(display) == 3002) && 1095a649c2abSJani Nikula src_x % 2 != 0) 1096a649c2abSJani Nikula hsub = 2; 1097a649c2abSJani Nikula } else { 1098a649c2abSJani Nikula hsub = fb->format->hsub; 1099a649c2abSJani Nikula vsub = fb->format->vsub; 1100a649c2abSJani Nikula } 1101a649c2abSJani Nikula 1102a649c2abSJani Nikula if (rotated) 1103a649c2abSJani Nikula hsub = vsub = max(hsub, vsub); 1104a649c2abSJani Nikula 1105a649c2abSJani Nikula if (src_x % hsub || src_w % hsub) { 1106a649c2abSJani Nikula drm_dbg_kms(display->drm, 1107a649c2abSJani Nikula "[PLANE:%d:%s] src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n", 1108a649c2abSJani Nikula plane->base.base.id, plane->base.name, 1109a649c2abSJani Nikula src_x, src_w, hsub, str_yes_no(rotated)); 1110a649c2abSJani Nikula return -EINVAL; 1111a649c2abSJani Nikula } 1112a649c2abSJani Nikula 1113a649c2abSJani Nikula if (src_y % vsub || src_h % vsub) { 1114a649c2abSJani Nikula drm_dbg_kms(display->drm, 1115a649c2abSJani Nikula "[PLANE:%d:%s] src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n", 1116a649c2abSJani Nikula plane->base.base.id, plane->base.name, 1117a649c2abSJani Nikula src_y, src_h, vsub, str_yes_no(rotated)); 1118a649c2abSJani Nikula return -EINVAL; 1119a649c2abSJani Nikula } 1120a649c2abSJani Nikula 1121a649c2abSJani Nikula return 0; 1122a649c2abSJani Nikula } 1123a649c2abSJani Nikula 1124a649c2abSJani Nikula static int add_dma_resv_fences(struct dma_resv *resv, 1125a649c2abSJani Nikula struct drm_plane_state *new_plane_state) 1126a649c2abSJani Nikula { 1127a649c2abSJani Nikula struct dma_fence *fence = dma_fence_get(new_plane_state->fence); 1128a649c2abSJani Nikula struct dma_fence *new; 1129a649c2abSJani Nikula int ret; 1130a649c2abSJani Nikula 1131a649c2abSJani Nikula ret = dma_resv_get_singleton(resv, dma_resv_usage_rw(false), &new); 1132a649c2abSJani Nikula if (ret) 1133a649c2abSJani Nikula goto error; 1134a649c2abSJani Nikula 1135a649c2abSJani Nikula if (new && fence) { 1136a649c2abSJani Nikula struct dma_fence_chain *chain = dma_fence_chain_alloc(); 1137a649c2abSJani Nikula 1138a649c2abSJani Nikula if (!chain) { 1139a649c2abSJani Nikula ret = -ENOMEM; 1140a649c2abSJani Nikula goto error; 1141a649c2abSJani Nikula } 1142a649c2abSJani Nikula 1143a649c2abSJani Nikula dma_fence_chain_init(chain, fence, new, 1); 1144a649c2abSJani Nikula fence = &chain->base; 1145a649c2abSJani Nikula 1146a649c2abSJani Nikula } else if (new) { 1147a649c2abSJani Nikula fence = new; 1148a649c2abSJani Nikula } 1149a649c2abSJani Nikula 1150a649c2abSJani Nikula dma_fence_put(new_plane_state->fence); 1151a649c2abSJani Nikula new_plane_state->fence = fence; 1152a649c2abSJani Nikula return 0; 1153a649c2abSJani Nikula 1154a649c2abSJani Nikula error: 1155a649c2abSJani Nikula dma_fence_put(fence); 1156a649c2abSJani Nikula return ret; 1157a649c2abSJani Nikula } 1158a649c2abSJani Nikula 1159a649c2abSJani Nikula /** 1160a649c2abSJani Nikula * intel_prepare_plane_fb - Prepare fb for usage on plane 1161a649c2abSJani Nikula * @_plane: drm plane to prepare for 1162a649c2abSJani Nikula * @_new_plane_state: the plane state being prepared 1163a649c2abSJani Nikula * 1164a649c2abSJani Nikula * Prepares a framebuffer for usage on a display plane. Generally this 1165a649c2abSJani Nikula * involves pinning the underlying object and updating the frontbuffer tracking 1166a649c2abSJani Nikula * bits. Some older platforms need special physical address handling for 1167a649c2abSJani Nikula * cursor planes. 1168a649c2abSJani Nikula * 1169a649c2abSJani Nikula * Returns 0 on success, negative error code on failure. 1170a649c2abSJani Nikula */ 1171a649c2abSJani Nikula static int 1172a649c2abSJani Nikula intel_prepare_plane_fb(struct drm_plane *_plane, 1173a649c2abSJani Nikula struct drm_plane_state *_new_plane_state) 1174a649c2abSJani Nikula { 1175a649c2abSJani Nikula struct i915_sched_attr attr = { .priority = I915_PRIORITY_DISPLAY }; 1176a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(_plane); 1177a649c2abSJani Nikula struct intel_display *display = to_intel_display(plane); 1178a649c2abSJani Nikula struct intel_plane_state *new_plane_state = 1179a649c2abSJani Nikula to_intel_plane_state(_new_plane_state); 1180a649c2abSJani Nikula struct intel_atomic_state *state = 1181a649c2abSJani Nikula to_intel_atomic_state(new_plane_state->uapi.state); 1182a649c2abSJani Nikula struct intel_plane_state *old_plane_state = 1183a649c2abSJani Nikula intel_atomic_get_old_plane_state(state, plane); 1184a649c2abSJani Nikula struct drm_gem_object *obj = intel_fb_bo(new_plane_state->hw.fb); 1185a649c2abSJani Nikula struct drm_gem_object *old_obj = intel_fb_bo(old_plane_state->hw.fb); 1186a649c2abSJani Nikula int ret; 1187a649c2abSJani Nikula 1188a649c2abSJani Nikula if (old_obj) { 1189a649c2abSJani Nikula const struct intel_crtc_state *new_crtc_state = 1190a649c2abSJani Nikula intel_atomic_get_new_crtc_state(state, 1191a649c2abSJani Nikula to_intel_crtc(old_plane_state->hw.crtc)); 1192a649c2abSJani Nikula 1193a649c2abSJani Nikula /* Big Hammer, we also need to ensure that any pending 1194a649c2abSJani Nikula * MI_WAIT_FOR_EVENT inside a user batch buffer on the 1195a649c2abSJani Nikula * current scanout is retired before unpinning the old 1196a649c2abSJani Nikula * framebuffer. Note that we rely on userspace rendering 1197a649c2abSJani Nikula * into the buffer attached to the pipe they are waiting 1198a649c2abSJani Nikula * on. If not, userspace generates a GPU hang with IPEHR 1199a649c2abSJani Nikula * point to the MI_WAIT_FOR_EVENT. 1200a649c2abSJani Nikula * 1201a649c2abSJani Nikula * This should only fail upon a hung GPU, in which case we 1202a649c2abSJani Nikula * can safely continue. 1203a649c2abSJani Nikula */ 1204a649c2abSJani Nikula if (intel_crtc_needs_modeset(new_crtc_state)) { 1205a649c2abSJani Nikula ret = add_dma_resv_fences(old_obj->resv, 1206a649c2abSJani Nikula &new_plane_state->uapi); 1207a649c2abSJani Nikula if (ret < 0) 1208a649c2abSJani Nikula return ret; 1209a649c2abSJani Nikula } 1210a649c2abSJani Nikula } 1211a649c2abSJani Nikula 1212a649c2abSJani Nikula if (!obj) 1213a649c2abSJani Nikula return 0; 1214a649c2abSJani Nikula 1215a649c2abSJani Nikula ret = intel_plane_pin_fb(new_plane_state, old_plane_state); 1216a649c2abSJani Nikula if (ret) 1217a649c2abSJani Nikula return ret; 1218a649c2abSJani Nikula 1219a649c2abSJani Nikula ret = drm_gem_plane_helper_prepare_fb(&plane->base, &new_plane_state->uapi); 1220a649c2abSJani Nikula if (ret < 0) 1221a649c2abSJani Nikula goto unpin_fb; 1222a649c2abSJani Nikula 1223a649c2abSJani Nikula if (new_plane_state->uapi.fence) { 1224a649c2abSJani Nikula i915_gem_fence_wait_priority(new_plane_state->uapi.fence, 1225a649c2abSJani Nikula &attr); 1226a649c2abSJani Nikula 1227a649c2abSJani Nikula intel_display_rps_boost_after_vblank(new_plane_state->hw.crtc, 1228a649c2abSJani Nikula new_plane_state->uapi.fence); 1229a649c2abSJani Nikula } 1230a649c2abSJani Nikula 1231a649c2abSJani Nikula /* 1232a649c2abSJani Nikula * We declare pageflips to be interactive and so merit a small bias 1233a649c2abSJani Nikula * towards upclocking to deliver the frame on time. By only changing 1234a649c2abSJani Nikula * the RPS thresholds to sample more regularly and aim for higher 1235a649c2abSJani Nikula * clocks we can hopefully deliver low power workloads (like kodi) 1236a649c2abSJani Nikula * that are not quite steady state without resorting to forcing 1237a649c2abSJani Nikula * maximum clocks following a vblank miss (see do_rps_boost()). 1238a649c2abSJani Nikula */ 1239a649c2abSJani Nikula intel_display_rps_mark_interactive(display, state, true); 1240a649c2abSJani Nikula 1241a649c2abSJani Nikula return 0; 1242a649c2abSJani Nikula 1243a649c2abSJani Nikula unpin_fb: 1244a649c2abSJani Nikula intel_plane_unpin_fb(new_plane_state); 1245a649c2abSJani Nikula 1246a649c2abSJani Nikula return ret; 1247a649c2abSJani Nikula } 1248a649c2abSJani Nikula 1249a649c2abSJani Nikula /** 1250a649c2abSJani Nikula * intel_cleanup_plane_fb - Cleans up an fb after plane use 1251a649c2abSJani Nikula * @plane: drm plane to clean up for 1252a649c2abSJani Nikula * @_old_plane_state: the state from the previous modeset 1253a649c2abSJani Nikula * 1254a649c2abSJani Nikula * Cleans up a framebuffer that has just been removed from a plane. 1255a649c2abSJani Nikula */ 1256a649c2abSJani Nikula static void 1257a649c2abSJani Nikula intel_cleanup_plane_fb(struct drm_plane *plane, 1258a649c2abSJani Nikula struct drm_plane_state *_old_plane_state) 1259a649c2abSJani Nikula { 1260a649c2abSJani Nikula struct intel_display *display = to_intel_display(plane->dev); 1261a649c2abSJani Nikula struct intel_plane_state *old_plane_state = 1262a649c2abSJani Nikula to_intel_plane_state(_old_plane_state); 1263a649c2abSJani Nikula struct intel_atomic_state *state = 1264a649c2abSJani Nikula to_intel_atomic_state(old_plane_state->uapi.state); 1265a649c2abSJani Nikula struct drm_gem_object *obj = intel_fb_bo(old_plane_state->hw.fb); 1266a649c2abSJani Nikula 1267a649c2abSJani Nikula if (!obj) 1268a649c2abSJani Nikula return; 1269a649c2abSJani Nikula 1270a649c2abSJani Nikula intel_display_rps_mark_interactive(display, state, false); 1271a649c2abSJani Nikula 1272a649c2abSJani Nikula intel_plane_unpin_fb(old_plane_state); 1273a649c2abSJani Nikula } 1274a649c2abSJani Nikula 1275*116d86ddSJocelyn Falempe /* Handle Y-tiling, only if DPT is enabled (otherwise disabling tiling is easier) 1276*116d86ddSJocelyn Falempe * All DPT hardware have 128-bytes width tiling, so Y-tile dimension is 32x32 1277*116d86ddSJocelyn Falempe * pixels for 32bits pixels. 1278*116d86ddSJocelyn Falempe */ 1279*116d86ddSJocelyn Falempe #define YTILE_WIDTH 32 1280*116d86ddSJocelyn Falempe #define YTILE_HEIGHT 32 1281*116d86ddSJocelyn Falempe #define YTILE_SIZE (YTILE_WIDTH * YTILE_HEIGHT * 4) 1282*116d86ddSJocelyn Falempe 1283*116d86ddSJocelyn Falempe static unsigned int intel_ytile_get_offset(unsigned int width, unsigned int x, unsigned int y) 1284*116d86ddSJocelyn Falempe { 1285*116d86ddSJocelyn Falempe u32 offset; 1286*116d86ddSJocelyn Falempe unsigned int swizzle; 1287*116d86ddSJocelyn Falempe unsigned int width_in_blocks = DIV_ROUND_UP(width, 32); 1288*116d86ddSJocelyn Falempe 1289*116d86ddSJocelyn Falempe /* Block offset */ 1290*116d86ddSJocelyn Falempe offset = ((y / YTILE_HEIGHT) * width_in_blocks + (x / YTILE_WIDTH)) * YTILE_SIZE; 1291*116d86ddSJocelyn Falempe 1292*116d86ddSJocelyn Falempe x = x % YTILE_WIDTH; 1293*116d86ddSJocelyn Falempe y = y % YTILE_HEIGHT; 1294*116d86ddSJocelyn Falempe 1295*116d86ddSJocelyn Falempe /* bit order inside a block is x4 x3 x2 y4 y3 y2 y1 y0 x1 x0 */ 1296*116d86ddSJocelyn Falempe swizzle = (x & 3) | ((y & 0x1f) << 2) | ((x & 0x1c) << 5); 1297*116d86ddSJocelyn Falempe offset += swizzle * 4; 1298*116d86ddSJocelyn Falempe return offset; 1299*116d86ddSJocelyn Falempe } 1300*116d86ddSJocelyn Falempe 130131d886b6SJocelyn Falempe static void intel_panic_flush(struct drm_plane *plane) 130231d886b6SJocelyn Falempe { 130331d886b6SJocelyn Falempe struct intel_plane_state *plane_state = to_intel_plane_state(plane->state); 130431d886b6SJocelyn Falempe struct intel_plane *iplane = to_intel_plane(plane); 130531d886b6SJocelyn Falempe struct intel_display *display = to_intel_display(iplane); 130631d886b6SJocelyn Falempe struct drm_framebuffer *fb = plane_state->hw.fb; 130731d886b6SJocelyn Falempe struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 130831d886b6SJocelyn Falempe 130931d886b6SJocelyn Falempe intel_bo_panic_finish(intel_fb); 131031d886b6SJocelyn Falempe 131131d886b6SJocelyn Falempe /* Flush the cache and don't disable tiling if it's the fbdev framebuffer.*/ 131231d886b6SJocelyn Falempe if (intel_fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) { 131331d886b6SJocelyn Falempe struct iosys_map map; 131431d886b6SJocelyn Falempe 131531d886b6SJocelyn Falempe intel_fbdev_get_map(display->fbdev.fbdev, &map); 131631d886b6SJocelyn Falempe drm_clflush_virt_range(map.vaddr, fb->pitches[0] * fb->height); 131731d886b6SJocelyn Falempe return; 131831d886b6SJocelyn Falempe } 131931d886b6SJocelyn Falempe 132031d886b6SJocelyn Falempe if (fb->modifier && iplane->disable_tiling) 132131d886b6SJocelyn Falempe iplane->disable_tiling(iplane); 132231d886b6SJocelyn Falempe } 132331d886b6SJocelyn Falempe 1324*116d86ddSJocelyn Falempe static unsigned int (*intel_get_tiling_func(u64 fb_modifier))(unsigned int width, 1325*116d86ddSJocelyn Falempe unsigned int x, 1326*116d86ddSJocelyn Falempe unsigned int y) 1327*116d86ddSJocelyn Falempe { 1328*116d86ddSJocelyn Falempe switch (fb_modifier) { 1329*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_Y_TILED: 1330*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_Y_TILED_CCS: 1331*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: 1332*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: 1333*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: 1334*116d86ddSJocelyn Falempe return intel_ytile_get_offset; 1335*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED: 1336*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: 1337*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: 1338*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: 1339*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: 1340*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: 1341*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: 1342*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED_BMG_CCS: 1343*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_4_TILED_LNL_CCS: 1344*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_X_TILED: 1345*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_Yf_TILED: 1346*116d86ddSJocelyn Falempe case I915_FORMAT_MOD_Yf_TILED_CCS: 1347*116d86ddSJocelyn Falempe default: 1348*116d86ddSJocelyn Falempe /* Not supported yet */ 1349*116d86ddSJocelyn Falempe return NULL; 1350*116d86ddSJocelyn Falempe } 1351*116d86ddSJocelyn Falempe } 1352*116d86ddSJocelyn Falempe 135331d886b6SJocelyn Falempe static int intel_get_scanout_buffer(struct drm_plane *plane, 135431d886b6SJocelyn Falempe struct drm_scanout_buffer *sb) 135531d886b6SJocelyn Falempe { 135631d886b6SJocelyn Falempe struct intel_plane_state *plane_state; 135731d886b6SJocelyn Falempe struct drm_gem_object *obj; 135831d886b6SJocelyn Falempe struct drm_framebuffer *fb; 135931d886b6SJocelyn Falempe struct intel_framebuffer *intel_fb; 136031d886b6SJocelyn Falempe struct intel_display *display = to_intel_display(plane->dev); 136131d886b6SJocelyn Falempe 136231d886b6SJocelyn Falempe if (!plane->state || !plane->state->fb || !plane->state->visible) 136331d886b6SJocelyn Falempe return -ENODEV; 136431d886b6SJocelyn Falempe 136531d886b6SJocelyn Falempe plane_state = to_intel_plane_state(plane->state); 136631d886b6SJocelyn Falempe fb = plane_state->hw.fb; 136731d886b6SJocelyn Falempe intel_fb = to_intel_framebuffer(fb); 136831d886b6SJocelyn Falempe 136931d886b6SJocelyn Falempe obj = intel_fb_bo(fb); 137031d886b6SJocelyn Falempe if (!obj) 137131d886b6SJocelyn Falempe return -ENODEV; 137231d886b6SJocelyn Falempe 137331d886b6SJocelyn Falempe if (intel_fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) { 137431d886b6SJocelyn Falempe intel_fbdev_get_map(display->fbdev.fbdev, &sb->map[0]); 137531d886b6SJocelyn Falempe } else { 137631d886b6SJocelyn Falempe int ret; 137731d886b6SJocelyn Falempe /* Can't disable tiling if DPT is in use */ 1378*116d86ddSJocelyn Falempe if (intel_fb_uses_dpt(fb)) { 1379*116d86ddSJocelyn Falempe if (fb->format->cpp[0] != 4) 138031d886b6SJocelyn Falempe return -EOPNOTSUPP; 1381*116d86ddSJocelyn Falempe intel_fb->panic_tiling = intel_get_tiling_func(fb->modifier); 1382*116d86ddSJocelyn Falempe if (!intel_fb->panic_tiling) 1383*116d86ddSJocelyn Falempe return -EOPNOTSUPP; 1384*116d86ddSJocelyn Falempe } 138531d886b6SJocelyn Falempe sb->private = intel_fb; 138631d886b6SJocelyn Falempe ret = intel_bo_panic_setup(sb); 138731d886b6SJocelyn Falempe if (ret) 138831d886b6SJocelyn Falempe return ret; 138931d886b6SJocelyn Falempe } 139031d886b6SJocelyn Falempe sb->width = fb->width; 139131d886b6SJocelyn Falempe sb->height = fb->height; 139231d886b6SJocelyn Falempe /* Use the generic linear format, because tiling, RC, CCS, CC 139331d886b6SJocelyn Falempe * will be disabled in disable_tiling() 139431d886b6SJocelyn Falempe */ 139531d886b6SJocelyn Falempe sb->format = drm_format_info(fb->format->format); 139631d886b6SJocelyn Falempe sb->pitch[0] = fb->pitches[0]; 139731d886b6SJocelyn Falempe 139831d886b6SJocelyn Falempe return 0; 139931d886b6SJocelyn Falempe } 140031d886b6SJocelyn Falempe 1401a649c2abSJani Nikula static const struct drm_plane_helper_funcs intel_plane_helper_funcs = { 1402a649c2abSJani Nikula .prepare_fb = intel_prepare_plane_fb, 1403a649c2abSJani Nikula .cleanup_fb = intel_cleanup_plane_fb, 1404a649c2abSJani Nikula }; 1405a649c2abSJani Nikula 140631d886b6SJocelyn Falempe static const struct drm_plane_helper_funcs intel_primary_plane_helper_funcs = { 140731d886b6SJocelyn Falempe .prepare_fb = intel_prepare_plane_fb, 140831d886b6SJocelyn Falempe .cleanup_fb = intel_cleanup_plane_fb, 140931d886b6SJocelyn Falempe .get_scanout_buffer = intel_get_scanout_buffer, 141031d886b6SJocelyn Falempe .panic_flush = intel_panic_flush, 141131d886b6SJocelyn Falempe }; 141231d886b6SJocelyn Falempe 1413a649c2abSJani Nikula void intel_plane_helper_add(struct intel_plane *plane) 1414a649c2abSJani Nikula { 141531d886b6SJocelyn Falempe if (plane->base.type == DRM_PLANE_TYPE_PRIMARY) 141631d886b6SJocelyn Falempe drm_plane_helper_add(&plane->base, &intel_primary_plane_helper_funcs); 141731d886b6SJocelyn Falempe else 1418a649c2abSJani Nikula drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); 1419a649c2abSJani Nikula } 1420a649c2abSJani Nikula 1421a649c2abSJani Nikula void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_state, 1422a649c2abSJani Nikula struct intel_plane_state *new_plane_state) 1423a649c2abSJani Nikula { 1424a649c2abSJani Nikula if (!old_plane_state->ggtt_vma || 1425a649c2abSJani Nikula old_plane_state->ggtt_vma == new_plane_state->ggtt_vma) 1426a649c2abSJani Nikula return; 1427a649c2abSJani Nikula 1428a649c2abSJani Nikula drm_vblank_work_init(&old_plane_state->unpin_work, old_plane_state->uapi.crtc, 1429a649c2abSJani Nikula intel_cursor_unpin_work); 1430a649c2abSJani Nikula } 1431a649c2abSJani Nikula 1432a649c2abSJani Nikula static void link_nv12_planes(struct intel_crtc_state *crtc_state, 1433a649c2abSJani Nikula struct intel_plane_state *uv_plane_state, 1434a649c2abSJani Nikula struct intel_plane_state *y_plane_state) 1435a649c2abSJani Nikula { 1436a649c2abSJani Nikula struct intel_display *display = to_intel_display(uv_plane_state); 1437a649c2abSJani Nikula struct intel_plane *uv_plane = to_intel_plane(uv_plane_state->uapi.plane); 1438a649c2abSJani Nikula struct intel_plane *y_plane = to_intel_plane(y_plane_state->uapi.plane); 1439a649c2abSJani Nikula 1440a649c2abSJani Nikula drm_dbg_kms(display->drm, "UV plane [PLANE:%d:%s] using Y plane [PLANE:%d:%s]\n", 1441a649c2abSJani Nikula uv_plane->base.base.id, uv_plane->base.name, 1442a649c2abSJani Nikula y_plane->base.base.id, y_plane->base.name); 1443a649c2abSJani Nikula 1444a649c2abSJani Nikula uv_plane_state->planar_linked_plane = y_plane; 1445a649c2abSJani Nikula 1446a649c2abSJani Nikula y_plane_state->is_y_plane = true; 1447a649c2abSJani Nikula y_plane_state->planar_linked_plane = uv_plane; 1448a649c2abSJani Nikula 1449a649c2abSJani Nikula crtc_state->enabled_planes |= BIT(y_plane->id); 1450a649c2abSJani Nikula crtc_state->active_planes |= BIT(y_plane->id); 1451a649c2abSJani Nikula crtc_state->update_planes |= BIT(y_plane->id); 1452a649c2abSJani Nikula 1453a649c2abSJani Nikula crtc_state->data_rate[y_plane->id] = crtc_state->data_rate_y[uv_plane->id]; 1454a649c2abSJani Nikula crtc_state->rel_data_rate[y_plane->id] = crtc_state->rel_data_rate_y[uv_plane->id]; 1455a649c2abSJani Nikula 1456a649c2abSJani Nikula /* Copy parameters to Y plane */ 1457a649c2abSJani Nikula intel_plane_copy_hw_state(y_plane_state, uv_plane_state); 1458a649c2abSJani Nikula y_plane_state->uapi.src = uv_plane_state->uapi.src; 1459a649c2abSJani Nikula y_plane_state->uapi.dst = uv_plane_state->uapi.dst; 1460a649c2abSJani Nikula 1461a649c2abSJani Nikula y_plane_state->ctl = uv_plane_state->ctl; 1462a649c2abSJani Nikula y_plane_state->color_ctl = uv_plane_state->color_ctl; 1463a649c2abSJani Nikula y_plane_state->view = uv_plane_state->view; 1464a649c2abSJani Nikula y_plane_state->decrypt = uv_plane_state->decrypt; 1465a649c2abSJani Nikula 1466a649c2abSJani Nikula icl_link_nv12_planes(uv_plane_state, y_plane_state); 1467a649c2abSJani Nikula } 1468a649c2abSJani Nikula 1469a649c2abSJani Nikula static void unlink_nv12_plane(struct intel_crtc_state *crtc_state, 1470a649c2abSJani Nikula struct intel_plane_state *plane_state) 1471a649c2abSJani Nikula { 1472a649c2abSJani Nikula struct intel_display *display = to_intel_display(plane_state); 1473a649c2abSJani Nikula struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1474a649c2abSJani Nikula 1475a649c2abSJani Nikula plane_state->planar_linked_plane = NULL; 1476a649c2abSJani Nikula 1477a649c2abSJani Nikula if (!plane_state->is_y_plane) 1478a649c2abSJani Nikula return; 1479a649c2abSJani Nikula 1480a649c2abSJani Nikula drm_WARN_ON(display->drm, plane_state->uapi.visible); 1481a649c2abSJani Nikula 1482a649c2abSJani Nikula plane_state->is_y_plane = false; 1483a649c2abSJani Nikula 1484a649c2abSJani Nikula crtc_state->enabled_planes &= ~BIT(plane->id); 1485a649c2abSJani Nikula crtc_state->active_planes &= ~BIT(plane->id); 1486a649c2abSJani Nikula crtc_state->update_planes |= BIT(plane->id); 1487a649c2abSJani Nikula crtc_state->data_rate[plane->id] = 0; 1488a649c2abSJani Nikula crtc_state->rel_data_rate[plane->id] = 0; 1489a649c2abSJani Nikula } 1490a649c2abSJani Nikula 1491a649c2abSJani Nikula static int icl_check_nv12_planes(struct intel_atomic_state *state, 1492a649c2abSJani Nikula struct intel_crtc *crtc) 1493a649c2abSJani Nikula { 1494a649c2abSJani Nikula struct intel_display *display = to_intel_display(state); 1495a649c2abSJani Nikula struct intel_crtc_state *crtc_state = 1496a649c2abSJani Nikula intel_atomic_get_new_crtc_state(state, crtc); 1497a649c2abSJani Nikula struct intel_plane_state *plane_state; 1498a649c2abSJani Nikula struct intel_plane *plane; 1499a649c2abSJani Nikula int i; 1500a649c2abSJani Nikula 1501a649c2abSJani Nikula if (DISPLAY_VER(display) < 11) 1502a649c2abSJani Nikula return 0; 1503a649c2abSJani Nikula 1504a649c2abSJani Nikula /* 1505a649c2abSJani Nikula * Destroy all old plane links and make the Y plane invisible 1506a649c2abSJani Nikula * in the crtc_state->active_planes mask. 1507a649c2abSJani Nikula */ 1508a649c2abSJani Nikula for_each_new_intel_plane_in_state(state, plane, plane_state, i) { 1509a649c2abSJani Nikula if (plane->pipe != crtc->pipe) 1510a649c2abSJani Nikula continue; 1511a649c2abSJani Nikula 1512a649c2abSJani Nikula if (plane_state->planar_linked_plane) 1513a649c2abSJani Nikula unlink_nv12_plane(crtc_state, plane_state); 1514a649c2abSJani Nikula } 1515a649c2abSJani Nikula 1516a649c2abSJani Nikula if (!crtc_state->nv12_planes) 1517a649c2abSJani Nikula return 0; 1518a649c2abSJani Nikula 1519a649c2abSJani Nikula for_each_new_intel_plane_in_state(state, plane, plane_state, i) { 1520a649c2abSJani Nikula struct intel_plane_state *y_plane_state = NULL; 1521a649c2abSJani Nikula struct intel_plane *y_plane; 1522a649c2abSJani Nikula 1523a649c2abSJani Nikula if (plane->pipe != crtc->pipe) 1524a649c2abSJani Nikula continue; 1525a649c2abSJani Nikula 1526a649c2abSJani Nikula if ((crtc_state->nv12_planes & BIT(plane->id)) == 0) 1527a649c2abSJani Nikula continue; 1528a649c2abSJani Nikula 1529a649c2abSJani Nikula for_each_intel_plane_on_crtc(display->drm, crtc, y_plane) { 1530a649c2abSJani Nikula if (!icl_is_nv12_y_plane(display, y_plane->id)) 1531a649c2abSJani Nikula continue; 1532a649c2abSJani Nikula 1533a649c2abSJani Nikula if (crtc_state->active_planes & BIT(y_plane->id)) 1534a649c2abSJani Nikula continue; 1535a649c2abSJani Nikula 1536a649c2abSJani Nikula y_plane_state = intel_atomic_get_plane_state(state, y_plane); 1537a649c2abSJani Nikula if (IS_ERR(y_plane_state)) 1538a649c2abSJani Nikula return PTR_ERR(y_plane_state); 1539a649c2abSJani Nikula 1540a649c2abSJani Nikula break; 1541a649c2abSJani Nikula } 1542a649c2abSJani Nikula 1543a649c2abSJani Nikula if (!y_plane_state) { 1544a649c2abSJani Nikula drm_dbg_kms(display->drm, 1545a649c2abSJani Nikula "[CRTC:%d:%s] need %d free Y planes for planar YUV\n", 1546a649c2abSJani Nikula crtc->base.base.id, crtc->base.name, 1547a649c2abSJani Nikula hweight8(crtc_state->nv12_planes)); 1548a649c2abSJani Nikula return -EINVAL; 1549a649c2abSJani Nikula } 1550a649c2abSJani Nikula 1551a649c2abSJani Nikula link_nv12_planes(crtc_state, plane_state, y_plane_state); 1552a649c2abSJani Nikula } 1553a649c2abSJani Nikula 1554a649c2abSJani Nikula return 0; 1555a649c2abSJani Nikula } 1556a649c2abSJani Nikula 1557a649c2abSJani Nikula static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state, 1558a649c2abSJani Nikula struct intel_crtc *crtc, 1559a649c2abSJani Nikula u8 plane_ids_mask) 1560a649c2abSJani Nikula { 1561a649c2abSJani Nikula struct intel_display *display = to_intel_display(state); 1562a649c2abSJani Nikula struct intel_plane *plane; 1563a649c2abSJani Nikula 1564a649c2abSJani Nikula for_each_intel_plane_on_crtc(display->drm, crtc, plane) { 1565a649c2abSJani Nikula struct intel_plane_state *plane_state; 1566a649c2abSJani Nikula 1567a649c2abSJani Nikula if ((plane_ids_mask & BIT(plane->id)) == 0) 1568a649c2abSJani Nikula continue; 1569a649c2abSJani Nikula 1570a649c2abSJani Nikula plane_state = intel_atomic_get_plane_state(state, plane); 1571a649c2abSJani Nikula if (IS_ERR(plane_state)) 1572a649c2abSJani Nikula return PTR_ERR(plane_state); 1573a649c2abSJani Nikula } 1574a649c2abSJani Nikula 1575a649c2abSJani Nikula return 0; 1576a649c2abSJani Nikula } 1577a649c2abSJani Nikula 1578be8f5f88SJani Nikula int intel_plane_add_affected(struct intel_atomic_state *state, 1579a649c2abSJani Nikula struct intel_crtc *crtc) 1580a649c2abSJani Nikula { 1581a649c2abSJani Nikula const struct intel_crtc_state *old_crtc_state = 1582a649c2abSJani Nikula intel_atomic_get_old_crtc_state(state, crtc); 1583a649c2abSJani Nikula const struct intel_crtc_state *new_crtc_state = 1584a649c2abSJani Nikula intel_atomic_get_new_crtc_state(state, crtc); 1585a649c2abSJani Nikula 1586a649c2abSJani Nikula return intel_crtc_add_planes_to_state(state, crtc, 1587a649c2abSJani Nikula old_crtc_state->enabled_planes | 1588a649c2abSJani Nikula new_crtc_state->enabled_planes); 1589a649c2abSJani Nikula } 1590a649c2abSJani Nikula 1591a649c2abSJani Nikula static bool active_planes_affects_min_cdclk(struct intel_display *display) 1592a649c2abSJani Nikula { 1593a649c2abSJani Nikula /* See {hsw,vlv,ivb}_plane_ratio() */ 1594a649c2abSJani Nikula return display->platform.broadwell || display->platform.haswell || 1595a649c2abSJani Nikula display->platform.cherryview || display->platform.valleyview || 1596a649c2abSJani Nikula display->platform.ivybridge; 1597a649c2abSJani Nikula } 1598a649c2abSJani Nikula 1599a649c2abSJani Nikula static u8 intel_joiner_affected_planes(struct intel_atomic_state *state, 1600a649c2abSJani Nikula u8 joined_pipes) 1601a649c2abSJani Nikula { 1602a649c2abSJani Nikula const struct intel_plane_state *plane_state; 1603a649c2abSJani Nikula struct intel_plane *plane; 1604a649c2abSJani Nikula u8 affected_planes = 0; 1605a649c2abSJani Nikula int i; 1606a649c2abSJani Nikula 1607a649c2abSJani Nikula for_each_new_intel_plane_in_state(state, plane, plane_state, i) { 1608a649c2abSJani Nikula struct intel_plane *linked = plane_state->planar_linked_plane; 1609a649c2abSJani Nikula 1610a649c2abSJani Nikula if ((joined_pipes & BIT(plane->pipe)) == 0) 1611a649c2abSJani Nikula continue; 1612a649c2abSJani Nikula 1613a649c2abSJani Nikula affected_planes |= BIT(plane->id); 1614a649c2abSJani Nikula if (linked) 1615a649c2abSJani Nikula affected_planes |= BIT(linked->id); 1616a649c2abSJani Nikula } 1617a649c2abSJani Nikula 1618a649c2abSJani Nikula return affected_planes; 1619a649c2abSJani Nikula } 1620a649c2abSJani Nikula 1621a649c2abSJani Nikula static int intel_joiner_add_affected_planes(struct intel_atomic_state *state, 1622a649c2abSJani Nikula u8 joined_pipes) 1623a649c2abSJani Nikula { 1624a649c2abSJani Nikula u8 prev_affected_planes, affected_planes = 0; 1625a649c2abSJani Nikula 1626a649c2abSJani Nikula /* 1627a649c2abSJani Nikula * We want all the joined pipes to have the same 1628a649c2abSJani Nikula * set of planes in the atomic state, to make sure 1629a649c2abSJani Nikula * state copying always works correctly, and the 1630a649c2abSJani Nikula * UV<->Y plane linkage is always up to date. 1631a649c2abSJani Nikula * Keep pulling planes in until we've determined 1632a649c2abSJani Nikula * the full set of affected planes. A bit complicated 1633a649c2abSJani Nikula * on account of each pipe being capable of selecting 1634a649c2abSJani Nikula * their own Y planes independently of the other pipes, 1635a649c2abSJani Nikula * and the selection being done from the set of 1636a649c2abSJani Nikula * inactive planes. 1637a649c2abSJani Nikula */ 1638a649c2abSJani Nikula do { 1639a649c2abSJani Nikula struct intel_crtc *crtc; 1640a649c2abSJani Nikula 1641a649c2abSJani Nikula for_each_intel_crtc_in_pipe_mask(state->base.dev, crtc, joined_pipes) { 1642a649c2abSJani Nikula int ret; 1643a649c2abSJani Nikula 1644a649c2abSJani Nikula ret = intel_crtc_add_planes_to_state(state, crtc, affected_planes); 1645a649c2abSJani Nikula if (ret) 1646a649c2abSJani Nikula return ret; 1647a649c2abSJani Nikula } 1648a649c2abSJani Nikula 1649a649c2abSJani Nikula prev_affected_planes = affected_planes; 1650a649c2abSJani Nikula affected_planes = intel_joiner_affected_planes(state, joined_pipes); 1651a649c2abSJani Nikula } while (affected_planes != prev_affected_planes); 1652a649c2abSJani Nikula 1653a649c2abSJani Nikula return 0; 1654a649c2abSJani Nikula } 1655a649c2abSJani Nikula 1656a649c2abSJani Nikula static int intel_add_affected_planes(struct intel_atomic_state *state) 1657a649c2abSJani Nikula { 1658a649c2abSJani Nikula const struct intel_crtc_state *crtc_state; 1659a649c2abSJani Nikula struct intel_crtc *crtc; 1660a649c2abSJani Nikula int i; 1661a649c2abSJani Nikula 1662a649c2abSJani Nikula for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { 1663a649c2abSJani Nikula int ret; 1664a649c2abSJani Nikula 1665a649c2abSJani Nikula ret = intel_joiner_add_affected_planes(state, intel_crtc_joined_pipe_mask(crtc_state)); 1666a649c2abSJani Nikula if (ret) 1667a649c2abSJani Nikula return ret; 1668a649c2abSJani Nikula } 1669a649c2abSJani Nikula 1670a649c2abSJani Nikula return 0; 1671a649c2abSJani Nikula } 1672a649c2abSJani Nikula 1673b603034fSJani Nikula int intel_plane_atomic_check(struct intel_atomic_state *state) 1674a649c2abSJani Nikula { 1675a649c2abSJani Nikula struct intel_display *display = to_intel_display(state); 1676a649c2abSJani Nikula struct intel_crtc_state *old_crtc_state, *new_crtc_state; 1677a649c2abSJani Nikula struct intel_plane_state __maybe_unused *plane_state; 1678a649c2abSJani Nikula struct intel_plane *plane; 1679a649c2abSJani Nikula struct intel_crtc *crtc; 1680a649c2abSJani Nikula int i, ret; 1681a649c2abSJani Nikula 1682a649c2abSJani Nikula ret = intel_add_affected_planes(state); 1683a649c2abSJani Nikula if (ret) 1684a649c2abSJani Nikula return ret; 1685a649c2abSJani Nikula 1686a649c2abSJani Nikula for_each_new_intel_plane_in_state(state, plane, plane_state, i) { 168751c2590dSJani Nikula ret = plane_atomic_check(state, plane); 1688a649c2abSJani Nikula if (ret) { 1689a649c2abSJani Nikula drm_dbg_atomic(display->drm, 1690a649c2abSJani Nikula "[PLANE:%d:%s] atomic driver check failed\n", 1691a649c2abSJani Nikula plane->base.base.id, plane->base.name); 1692a649c2abSJani Nikula return ret; 1693a649c2abSJani Nikula } 1694a649c2abSJani Nikula } 1695a649c2abSJani Nikula 1696a649c2abSJani Nikula for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 1697a649c2abSJani Nikula new_crtc_state, i) { 1698a649c2abSJani Nikula u8 old_active_planes, new_active_planes; 1699a649c2abSJani Nikula 1700a649c2abSJani Nikula ret = icl_check_nv12_planes(state, crtc); 1701a649c2abSJani Nikula if (ret) 1702a649c2abSJani Nikula return ret; 1703a649c2abSJani Nikula 1704a649c2abSJani Nikula /* 1705a649c2abSJani Nikula * On some platforms the number of active planes affects 1706a649c2abSJani Nikula * the planes' minimum cdclk calculation. Add such planes 1707a649c2abSJani Nikula * to the state before we compute the minimum cdclk. 1708a649c2abSJani Nikula */ 1709a649c2abSJani Nikula if (!active_planes_affects_min_cdclk(display)) 1710a649c2abSJani Nikula continue; 1711a649c2abSJani Nikula 1712a649c2abSJani Nikula old_active_planes = old_crtc_state->active_planes & ~BIT(PLANE_CURSOR); 1713a649c2abSJani Nikula new_active_planes = new_crtc_state->active_planes & ~BIT(PLANE_CURSOR); 1714a649c2abSJani Nikula 1715a649c2abSJani Nikula if (hweight8(old_active_planes) == hweight8(new_active_planes)) 1716a649c2abSJani Nikula continue; 1717a649c2abSJani Nikula 1718a649c2abSJani Nikula ret = intel_crtc_add_planes_to_state(state, crtc, new_active_planes); 1719a649c2abSJani Nikula if (ret) 1720a649c2abSJani Nikula return ret; 1721a649c2abSJani Nikula } 1722a649c2abSJani Nikula 1723a649c2abSJani Nikula return 0; 1724a649c2abSJani Nikula } 1725a649c2abSJani Nikula 1726a649c2abSJani Nikula u32 intel_plane_ggtt_offset(const struct intel_plane_state *plane_state) 1727a649c2abSJani Nikula { 1728a649c2abSJani Nikula return i915_ggtt_offset(plane_state->ggtt_vma); 1729a649c2abSJani Nikula } 1730