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