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