1059f8782SVille Syrjälä // SPDX-License-Identifier: MIT 2059f8782SVille Syrjälä /* 3059f8782SVille Syrjälä * Copyright 2026, Intel Corporation. 4059f8782SVille Syrjälä */ 5059f8782SVille Syrjälä 6059f8782SVille Syrjälä #include <drm/drm_print.h> 7059f8782SVille Syrjälä 8e3f33adfSVille Syrjälä #include <drm/intel/display_parent_interface.h> 9059f8782SVille Syrjälä #include <drm/intel/intel_gmd_interrupt_regs.h> 10059f8782SVille Syrjälä 11059f8782SVille Syrjälä #include "gem/i915_gem_internal.h" 12059f8782SVille Syrjälä #include "gem/i915_gem_object_frontbuffer.h" 13059f8782SVille Syrjälä #include "gem/i915_gem_pm.h" 14059f8782SVille Syrjälä 15059f8782SVille Syrjälä #include "gt/intel_gpu_commands.h" 16059f8782SVille Syrjälä #include "gt/intel_ring.h" 17059f8782SVille Syrjälä 18059f8782SVille Syrjälä #include "i915_drv.h" 19059f8782SVille Syrjälä #include "i915_overlay.h" 20059f8782SVille Syrjälä #include "i915_reg.h" 21059f8782SVille Syrjälä #include "intel_pci_config.h" 22059f8782SVille Syrjälä 23059f8782SVille Syrjälä #include "display/intel_frontbuffer.h" 24059f8782SVille Syrjälä 25059f8782SVille Syrjälä /* overlay flip addr flag */ 26059f8782SVille Syrjälä #define OFC_UPDATE 0x1 27059f8782SVille Syrjälä 28059f8782SVille Syrjälä struct i915_overlay { 29059f8782SVille Syrjälä struct drm_i915_private *i915; 30059f8782SVille Syrjälä struct intel_context *context; 31059f8782SVille Syrjälä struct i915_vma *vma; 32059f8782SVille Syrjälä struct i915_vma *old_vma; 33*df88ba89SJani Nikula struct i915_frontbuffer *frontbuffer; 34059f8782SVille Syrjälä /* register access */ 35059f8782SVille Syrjälä struct drm_i915_gem_object *reg_bo; 36059f8782SVille Syrjälä void __iomem *regs; 37059f8782SVille Syrjälä u32 flip_addr; 38059f8782SVille Syrjälä u32 frontbuffer_bits; 39059f8782SVille Syrjälä /* flip handling */ 40059f8782SVille Syrjälä struct i915_active last_flip; 41059f8782SVille Syrjälä void (*flip_complete)(struct i915_overlay *overlay); 42059f8782SVille Syrjälä }; 43059f8782SVille Syrjälä 44059f8782SVille Syrjälä static void i830_overlay_clock_gating(struct drm_i915_private *i915, 45059f8782SVille Syrjälä bool enable) 46059f8782SVille Syrjälä { 47059f8782SVille Syrjälä struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 48059f8782SVille Syrjälä u8 val; 49059f8782SVille Syrjälä 50059f8782SVille Syrjälä /* 51059f8782SVille Syrjälä * WA_OVERLAY_CLKGATE:alm 52059f8782SVille Syrjälä * 53059f8782SVille Syrjälä * FIXME should perhaps be done on the display side? 54059f8782SVille Syrjälä */ 55059f8782SVille Syrjälä if (enable) 56059f8782SVille Syrjälä intel_uncore_write(&i915->uncore, DSPCLK_GATE_D, 0); 57059f8782SVille Syrjälä else 58059f8782SVille Syrjälä intel_uncore_write(&i915->uncore, DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); 59059f8782SVille Syrjälä 60059f8782SVille Syrjälä /* WA_DISABLE_L2CACHE_CLOCK_GATING:alm */ 61059f8782SVille Syrjälä pci_bus_read_config_byte(pdev->bus, 62059f8782SVille Syrjälä PCI_DEVFN(0, 0), I830_CLOCK_GATE, &val); 63059f8782SVille Syrjälä if (enable) 64059f8782SVille Syrjälä val &= ~I830_L2_CACHE_CLOCK_GATE_DISABLE; 65059f8782SVille Syrjälä else 66059f8782SVille Syrjälä val |= I830_L2_CACHE_CLOCK_GATE_DISABLE; 67059f8782SVille Syrjälä pci_bus_write_config_byte(pdev->bus, 68059f8782SVille Syrjälä PCI_DEVFN(0, 0), I830_CLOCK_GATE, val); 69059f8782SVille Syrjälä } 70059f8782SVille Syrjälä 71059f8782SVille Syrjälä static struct i915_request * 72059f8782SVille Syrjälä alloc_request(struct i915_overlay *overlay, void (*fn)(struct i915_overlay *)) 73059f8782SVille Syrjälä { 74059f8782SVille Syrjälä struct i915_request *rq; 75059f8782SVille Syrjälä int err; 76059f8782SVille Syrjälä 77059f8782SVille Syrjälä overlay->flip_complete = fn; 78059f8782SVille Syrjälä 79059f8782SVille Syrjälä rq = i915_request_create(overlay->context); 80059f8782SVille Syrjälä if (IS_ERR(rq)) 81059f8782SVille Syrjälä return rq; 82059f8782SVille Syrjälä 83059f8782SVille Syrjälä err = i915_active_add_request(&overlay->last_flip, rq); 84059f8782SVille Syrjälä if (err) { 85059f8782SVille Syrjälä i915_request_add(rq); 86059f8782SVille Syrjälä return ERR_PTR(err); 87059f8782SVille Syrjälä } 88059f8782SVille Syrjälä 89059f8782SVille Syrjälä return rq; 90059f8782SVille Syrjälä } 91059f8782SVille Syrjälä 92e3f33adfSVille Syrjälä static bool i915_overlay_is_active(struct drm_device *drm) 93059f8782SVille Syrjälä { 94059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 95059f8782SVille Syrjälä struct i915_overlay *overlay = i915->overlay; 96059f8782SVille Syrjälä 97059f8782SVille Syrjälä return overlay->frontbuffer_bits; 98059f8782SVille Syrjälä } 99059f8782SVille Syrjälä 100059f8782SVille Syrjälä /* overlay needs to be disable in OCMD reg */ 101e3f33adfSVille Syrjälä static int i915_overlay_on(struct drm_device *drm, 102059f8782SVille Syrjälä u32 frontbuffer_bits) 103059f8782SVille Syrjälä { 104059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 105059f8782SVille Syrjälä struct i915_overlay *overlay = i915->overlay; 106059f8782SVille Syrjälä struct i915_request *rq; 107059f8782SVille Syrjälä u32 *cs; 108059f8782SVille Syrjälä 109059f8782SVille Syrjälä drm_WARN_ON(drm, i915_overlay_is_active(drm)); 110059f8782SVille Syrjälä 111059f8782SVille Syrjälä rq = alloc_request(overlay, NULL); 112059f8782SVille Syrjälä if (IS_ERR(rq)) 113059f8782SVille Syrjälä return PTR_ERR(rq); 114059f8782SVille Syrjälä 115059f8782SVille Syrjälä cs = intel_ring_begin(rq, 4); 116059f8782SVille Syrjälä if (IS_ERR(cs)) { 117059f8782SVille Syrjälä i915_request_add(rq); 118059f8782SVille Syrjälä return PTR_ERR(cs); 119059f8782SVille Syrjälä } 120059f8782SVille Syrjälä 121059f8782SVille Syrjälä overlay->frontbuffer_bits = frontbuffer_bits; 122059f8782SVille Syrjälä 123059f8782SVille Syrjälä if (IS_I830(i915)) 124059f8782SVille Syrjälä i830_overlay_clock_gating(i915, false); 125059f8782SVille Syrjälä 126059f8782SVille Syrjälä *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_ON; 127059f8782SVille Syrjälä *cs++ = overlay->flip_addr | OFC_UPDATE; 128059f8782SVille Syrjälä *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP; 129059f8782SVille Syrjälä *cs++ = MI_NOOP; 130059f8782SVille Syrjälä intel_ring_advance(rq, cs); 131059f8782SVille Syrjälä 132059f8782SVille Syrjälä i915_request_add(rq); 133059f8782SVille Syrjälä 134059f8782SVille Syrjälä return i915_active_wait(&overlay->last_flip); 135059f8782SVille Syrjälä } 136059f8782SVille Syrjälä 137059f8782SVille Syrjälä static void i915_overlay_flip_prepare(struct i915_overlay *overlay, 138059f8782SVille Syrjälä struct i915_vma *vma) 139059f8782SVille Syrjälä { 140059f8782SVille Syrjälä struct drm_i915_private *i915 = overlay->i915; 141*df88ba89SJani Nikula struct i915_frontbuffer *frontbuffer = NULL; 142059f8782SVille Syrjälä 143059f8782SVille Syrjälä drm_WARN_ON(&i915->drm, overlay->old_vma); 144059f8782SVille Syrjälä 145059f8782SVille Syrjälä if (vma) 146*df88ba89SJani Nikula frontbuffer = i915_gem_object_frontbuffer_get(vma->obj); 147059f8782SVille Syrjälä 148*df88ba89SJani Nikula i915_gem_object_frontbuffer_track(overlay->frontbuffer, frontbuffer, 149059f8782SVille Syrjälä overlay->frontbuffer_bits); 150059f8782SVille Syrjälä 151059f8782SVille Syrjälä if (overlay->frontbuffer) 152*df88ba89SJani Nikula i915_gem_object_frontbuffer_put(overlay->frontbuffer); 153059f8782SVille Syrjälä overlay->frontbuffer = frontbuffer; 154059f8782SVille Syrjälä 155059f8782SVille Syrjälä overlay->old_vma = overlay->vma; 156059f8782SVille Syrjälä if (vma) 157059f8782SVille Syrjälä overlay->vma = i915_vma_get(vma); 158059f8782SVille Syrjälä else 159059f8782SVille Syrjälä overlay->vma = NULL; 160059f8782SVille Syrjälä } 161059f8782SVille Syrjälä 162059f8782SVille Syrjälä /* overlay needs to be enabled in OCMD reg */ 163e3f33adfSVille Syrjälä static int i915_overlay_continue(struct drm_device *drm, 164059f8782SVille Syrjälä struct i915_vma *vma, 165059f8782SVille Syrjälä bool load_polyphase_filter) 166059f8782SVille Syrjälä { 167059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 168059f8782SVille Syrjälä struct i915_overlay *overlay = i915->overlay; 169059f8782SVille Syrjälä struct i915_request *rq; 170059f8782SVille Syrjälä u32 flip_addr = overlay->flip_addr; 171059f8782SVille Syrjälä u32 *cs; 172059f8782SVille Syrjälä 173059f8782SVille Syrjälä drm_WARN_ON(drm, !i915_overlay_is_active(drm)); 174059f8782SVille Syrjälä 175059f8782SVille Syrjälä if (load_polyphase_filter) 176059f8782SVille Syrjälä flip_addr |= OFC_UPDATE; 177059f8782SVille Syrjälä 178059f8782SVille Syrjälä rq = alloc_request(overlay, NULL); 179059f8782SVille Syrjälä if (IS_ERR(rq)) 180059f8782SVille Syrjälä return PTR_ERR(rq); 181059f8782SVille Syrjälä 182059f8782SVille Syrjälä cs = intel_ring_begin(rq, 2); 183059f8782SVille Syrjälä if (IS_ERR(cs)) { 184059f8782SVille Syrjälä i915_request_add(rq); 185059f8782SVille Syrjälä return PTR_ERR(cs); 186059f8782SVille Syrjälä } 187059f8782SVille Syrjälä 188059f8782SVille Syrjälä *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE; 189059f8782SVille Syrjälä *cs++ = flip_addr; 190059f8782SVille Syrjälä intel_ring_advance(rq, cs); 191059f8782SVille Syrjälä 192059f8782SVille Syrjälä i915_overlay_flip_prepare(overlay, vma); 193059f8782SVille Syrjälä i915_request_add(rq); 194059f8782SVille Syrjälä 195059f8782SVille Syrjälä return 0; 196059f8782SVille Syrjälä } 197059f8782SVille Syrjälä 198059f8782SVille Syrjälä static void i915_overlay_release_old_vma(struct i915_overlay *overlay) 199059f8782SVille Syrjälä { 200059f8782SVille Syrjälä struct drm_i915_private *i915 = overlay->i915; 201059f8782SVille Syrjälä struct intel_display *display = i915->display; 202059f8782SVille Syrjälä struct i915_vma *vma; 203059f8782SVille Syrjälä 204059f8782SVille Syrjälä vma = fetch_and_zero(&overlay->old_vma); 205059f8782SVille Syrjälä if (drm_WARN_ON(&i915->drm, !vma)) 206059f8782SVille Syrjälä return; 207059f8782SVille Syrjälä 208059f8782SVille Syrjälä intel_frontbuffer_flip(display, overlay->frontbuffer_bits); 209059f8782SVille Syrjälä 210059f8782SVille Syrjälä i915_vma_unpin(vma); 211059f8782SVille Syrjälä i915_vma_put(vma); 212059f8782SVille Syrjälä } 213059f8782SVille Syrjälä 214e3f33adfSVille Syrjälä static void 215e3f33adfSVille Syrjälä i915_overlay_release_old_vid_tail(struct i915_overlay *overlay) 216059f8782SVille Syrjälä { 217059f8782SVille Syrjälä i915_overlay_release_old_vma(overlay); 218059f8782SVille Syrjälä } 219059f8782SVille Syrjälä 220059f8782SVille Syrjälä static void i915_overlay_off_tail(struct i915_overlay *overlay) 221059f8782SVille Syrjälä { 222059f8782SVille Syrjälä struct drm_i915_private *i915 = overlay->i915; 223059f8782SVille Syrjälä 224059f8782SVille Syrjälä i915_overlay_release_old_vma(overlay); 225059f8782SVille Syrjälä 226059f8782SVille Syrjälä overlay->frontbuffer_bits = 0; 227059f8782SVille Syrjälä 228059f8782SVille Syrjälä if (IS_I830(i915)) 229059f8782SVille Syrjälä i830_overlay_clock_gating(i915, true); 230059f8782SVille Syrjälä } 231059f8782SVille Syrjälä 232059f8782SVille Syrjälä static void i915_overlay_last_flip_retire(struct i915_active *active) 233059f8782SVille Syrjälä { 234059f8782SVille Syrjälä struct i915_overlay *overlay = 235059f8782SVille Syrjälä container_of(active, typeof(*overlay), last_flip); 236059f8782SVille Syrjälä 237059f8782SVille Syrjälä if (overlay->flip_complete) 238059f8782SVille Syrjälä overlay->flip_complete(overlay); 239059f8782SVille Syrjälä } 240059f8782SVille Syrjälä 241059f8782SVille Syrjälä /* overlay needs to be disabled in OCMD reg */ 242e3f33adfSVille Syrjälä static int i915_overlay_off(struct drm_device *drm) 243059f8782SVille Syrjälä { 244059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 245059f8782SVille Syrjälä struct i915_overlay *overlay = i915->overlay; 246059f8782SVille Syrjälä struct i915_request *rq; 247059f8782SVille Syrjälä u32 *cs, flip_addr = overlay->flip_addr; 248059f8782SVille Syrjälä 249059f8782SVille Syrjälä drm_WARN_ON(drm, !i915_overlay_is_active(drm)); 250059f8782SVille Syrjälä 251059f8782SVille Syrjälä /* 252059f8782SVille Syrjälä * According to intel docs the overlay hw may hang (when switching 253059f8782SVille Syrjälä * off) without loading the filter coeffs. It is however unclear whether 254059f8782SVille Syrjälä * this applies to the disabling of the overlay or to the switching off 255059f8782SVille Syrjälä * of the hw. Do it in both cases. 256059f8782SVille Syrjälä */ 257059f8782SVille Syrjälä flip_addr |= OFC_UPDATE; 258059f8782SVille Syrjälä 259059f8782SVille Syrjälä rq = alloc_request(overlay, i915_overlay_off_tail); 260059f8782SVille Syrjälä if (IS_ERR(rq)) 261059f8782SVille Syrjälä return PTR_ERR(rq); 262059f8782SVille Syrjälä 263059f8782SVille Syrjälä cs = intel_ring_begin(rq, 6); 264059f8782SVille Syrjälä if (IS_ERR(cs)) { 265059f8782SVille Syrjälä i915_request_add(rq); 266059f8782SVille Syrjälä return PTR_ERR(cs); 267059f8782SVille Syrjälä } 268059f8782SVille Syrjälä 269059f8782SVille Syrjälä /* wait for overlay to go idle */ 270059f8782SVille Syrjälä *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE; 271059f8782SVille Syrjälä *cs++ = flip_addr; 272059f8782SVille Syrjälä *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP; 273059f8782SVille Syrjälä 274059f8782SVille Syrjälä /* turn overlay off */ 275059f8782SVille Syrjälä *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_OFF; 276059f8782SVille Syrjälä *cs++ = flip_addr; 277059f8782SVille Syrjälä *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP; 278059f8782SVille Syrjälä 279059f8782SVille Syrjälä intel_ring_advance(rq, cs); 280059f8782SVille Syrjälä 281059f8782SVille Syrjälä i915_overlay_flip_prepare(overlay, NULL); 282059f8782SVille Syrjälä i915_request_add(rq); 283059f8782SVille Syrjälä 284059f8782SVille Syrjälä return i915_active_wait(&overlay->last_flip); 285059f8782SVille Syrjälä } 286059f8782SVille Syrjälä 287059f8782SVille Syrjälä /* 288059f8782SVille Syrjälä * Recover from an interruption due to a signal. 289059f8782SVille Syrjälä * We have to be careful not to repeat work forever an make forward progress. 290059f8782SVille Syrjälä */ 291e3f33adfSVille Syrjälä static int i915_overlay_recover_from_interrupt(struct drm_device *drm) 292059f8782SVille Syrjälä { 293059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 294059f8782SVille Syrjälä struct i915_overlay *overlay = i915->overlay; 295059f8782SVille Syrjälä 296059f8782SVille Syrjälä return i915_active_wait(&overlay->last_flip); 297059f8782SVille Syrjälä } 298059f8782SVille Syrjälä 299059f8782SVille Syrjälä /* 300059f8782SVille Syrjälä * Wait for pending overlay flip and release old frame. 301059f8782SVille Syrjälä * Needs to be called before the overlay register are changed 302059f8782SVille Syrjälä * via intel_overlay_(un)map_regs. 303059f8782SVille Syrjälä */ 304e3f33adfSVille Syrjälä static int i915_overlay_release_old_vid(struct drm_device *drm) 305059f8782SVille Syrjälä { 306059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 307059f8782SVille Syrjälä struct i915_overlay *overlay = i915->overlay; 308059f8782SVille Syrjälä struct i915_request *rq; 309059f8782SVille Syrjälä u32 *cs; 310059f8782SVille Syrjälä 311059f8782SVille Syrjälä /* 312059f8782SVille Syrjälä * Only wait if there is actually an old frame to release to 313059f8782SVille Syrjälä * guarantee forward progress. 314059f8782SVille Syrjälä */ 315059f8782SVille Syrjälä if (!overlay->old_vma) 316059f8782SVille Syrjälä return 0; 317059f8782SVille Syrjälä 318059f8782SVille Syrjälä if (!(intel_uncore_read(&i915->uncore, GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) { 319059f8782SVille Syrjälä i915_overlay_release_old_vid_tail(overlay); 320059f8782SVille Syrjälä return 0; 321059f8782SVille Syrjälä } 322059f8782SVille Syrjälä 323059f8782SVille Syrjälä rq = alloc_request(overlay, i915_overlay_release_old_vid_tail); 324059f8782SVille Syrjälä if (IS_ERR(rq)) 325059f8782SVille Syrjälä return PTR_ERR(rq); 326059f8782SVille Syrjälä 327059f8782SVille Syrjälä cs = intel_ring_begin(rq, 2); 328059f8782SVille Syrjälä if (IS_ERR(cs)) { 329059f8782SVille Syrjälä i915_request_add(rq); 330059f8782SVille Syrjälä return PTR_ERR(cs); 331059f8782SVille Syrjälä } 332059f8782SVille Syrjälä 333059f8782SVille Syrjälä *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP; 334059f8782SVille Syrjälä *cs++ = MI_NOOP; 335059f8782SVille Syrjälä intel_ring_advance(rq, cs); 336059f8782SVille Syrjälä 337059f8782SVille Syrjälä i915_request_add(rq); 338059f8782SVille Syrjälä 339059f8782SVille Syrjälä return i915_active_wait(&overlay->last_flip); 340059f8782SVille Syrjälä } 341059f8782SVille Syrjälä 342e3f33adfSVille Syrjälä static void i915_overlay_reset(struct drm_device *drm) 343059f8782SVille Syrjälä { 344059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 345059f8782SVille Syrjälä struct i915_overlay *overlay = i915->overlay; 346059f8782SVille Syrjälä 347059f8782SVille Syrjälä if (!overlay) 348059f8782SVille Syrjälä return; 349059f8782SVille Syrjälä 350059f8782SVille Syrjälä overlay->frontbuffer_bits = 0; 351059f8782SVille Syrjälä } 352059f8782SVille Syrjälä 353e3f33adfSVille Syrjälä static struct i915_vma *i915_overlay_pin_fb(struct drm_device *drm, 354059f8782SVille Syrjälä struct drm_gem_object *obj, 355059f8782SVille Syrjälä u32 *offset) 356059f8782SVille Syrjälä { 357059f8782SVille Syrjälä struct drm_i915_gem_object *new_bo = to_intel_bo(obj); 358059f8782SVille Syrjälä struct i915_gem_ww_ctx ww; 359059f8782SVille Syrjälä struct i915_vma *vma; 360059f8782SVille Syrjälä int ret; 361059f8782SVille Syrjälä 362059f8782SVille Syrjälä i915_gem_ww_ctx_init(&ww, true); 363059f8782SVille Syrjälä retry: 364059f8782SVille Syrjälä ret = i915_gem_object_lock(new_bo, &ww); 365059f8782SVille Syrjälä if (!ret) { 366059f8782SVille Syrjälä vma = i915_gem_object_pin_to_display_plane(new_bo, &ww, 0, 0, 367059f8782SVille Syrjälä NULL, PIN_MAPPABLE); 368059f8782SVille Syrjälä ret = PTR_ERR_OR_ZERO(vma); 369059f8782SVille Syrjälä } 370059f8782SVille Syrjälä if (ret == -EDEADLK) { 371059f8782SVille Syrjälä ret = i915_gem_ww_ctx_backoff(&ww); 372059f8782SVille Syrjälä if (!ret) 373059f8782SVille Syrjälä goto retry; 374059f8782SVille Syrjälä } 375059f8782SVille Syrjälä i915_gem_ww_ctx_fini(&ww); 376059f8782SVille Syrjälä if (ret) 377059f8782SVille Syrjälä return ERR_PTR(ret); 378059f8782SVille Syrjälä 379059f8782SVille Syrjälä *offset = i915_ggtt_offset(vma); 380059f8782SVille Syrjälä 381059f8782SVille Syrjälä return vma; 382059f8782SVille Syrjälä } 383059f8782SVille Syrjälä 384e3f33adfSVille Syrjälä static void i915_overlay_unpin_fb(struct drm_device *drm, 385059f8782SVille Syrjälä struct i915_vma *vma) 386059f8782SVille Syrjälä { 387059f8782SVille Syrjälä i915_vma_unpin(vma); 388059f8782SVille Syrjälä } 389059f8782SVille Syrjälä 390e3f33adfSVille Syrjälä static struct drm_gem_object * 391059f8782SVille Syrjälä i915_overlay_obj_lookup(struct drm_device *drm, 392059f8782SVille Syrjälä struct drm_file *file_priv, 393059f8782SVille Syrjälä u32 handle) 394059f8782SVille Syrjälä { 395059f8782SVille Syrjälä struct drm_i915_gem_object *bo; 396059f8782SVille Syrjälä 397059f8782SVille Syrjälä bo = i915_gem_object_lookup(file_priv, handle); 398059f8782SVille Syrjälä if (!bo) 399059f8782SVille Syrjälä return ERR_PTR(-ENOENT); 400059f8782SVille Syrjälä 401059f8782SVille Syrjälä if (i915_gem_object_is_tiled(bo)) { 402059f8782SVille Syrjälä drm_dbg(drm, "buffer used for overlay image can not be tiled\n"); 403059f8782SVille Syrjälä i915_gem_object_put(bo); 404059f8782SVille Syrjälä return ERR_PTR(-EINVAL); 405059f8782SVille Syrjälä } 406059f8782SVille Syrjälä 407059f8782SVille Syrjälä return intel_bo_to_drm_bo(bo); 408059f8782SVille Syrjälä } 409059f8782SVille Syrjälä 410059f8782SVille Syrjälä static int get_registers(struct i915_overlay *overlay, bool use_phys) 411059f8782SVille Syrjälä { 412059f8782SVille Syrjälä struct drm_i915_private *i915 = overlay->i915; 413059f8782SVille Syrjälä struct drm_i915_gem_object *obj; 414059f8782SVille Syrjälä struct i915_vma *vma; 415059f8782SVille Syrjälä int err; 416059f8782SVille Syrjälä 417059f8782SVille Syrjälä obj = i915_gem_object_create_stolen(i915, PAGE_SIZE); 418059f8782SVille Syrjälä if (IS_ERR(obj)) 419059f8782SVille Syrjälä obj = i915_gem_object_create_internal(i915, PAGE_SIZE); 420059f8782SVille Syrjälä if (IS_ERR(obj)) 421059f8782SVille Syrjälä return PTR_ERR(obj); 422059f8782SVille Syrjälä 423059f8782SVille Syrjälä vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE); 424059f8782SVille Syrjälä if (IS_ERR(vma)) { 425059f8782SVille Syrjälä err = PTR_ERR(vma); 426059f8782SVille Syrjälä goto err_put_bo; 427059f8782SVille Syrjälä } 428059f8782SVille Syrjälä 429059f8782SVille Syrjälä if (use_phys) 430059f8782SVille Syrjälä overlay->flip_addr = sg_dma_address(obj->mm.pages->sgl); 431059f8782SVille Syrjälä else 432059f8782SVille Syrjälä overlay->flip_addr = i915_ggtt_offset(vma); 433059f8782SVille Syrjälä overlay->regs = i915_vma_pin_iomap(vma); 434059f8782SVille Syrjälä i915_vma_unpin(vma); 435059f8782SVille Syrjälä 436059f8782SVille Syrjälä if (IS_ERR(overlay->regs)) { 437059f8782SVille Syrjälä err = PTR_ERR(overlay->regs); 438059f8782SVille Syrjälä goto err_put_bo; 439059f8782SVille Syrjälä } 440059f8782SVille Syrjälä 441059f8782SVille Syrjälä overlay->reg_bo = obj; 442059f8782SVille Syrjälä return 0; 443059f8782SVille Syrjälä 444059f8782SVille Syrjälä err_put_bo: 445059f8782SVille Syrjälä i915_gem_object_put(obj); 446059f8782SVille Syrjälä return err; 447059f8782SVille Syrjälä } 448059f8782SVille Syrjälä 449e3f33adfSVille Syrjälä static void __iomem *i915_overlay_setup(struct drm_device *drm, 450059f8782SVille Syrjälä bool needs_physical) 451059f8782SVille Syrjälä { 452059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 453059f8782SVille Syrjälä struct intel_engine_cs *engine; 454059f8782SVille Syrjälä struct i915_overlay *overlay; 455059f8782SVille Syrjälä int ret; 456059f8782SVille Syrjälä 457059f8782SVille Syrjälä engine = to_gt(i915)->engine[RCS0]; 458059f8782SVille Syrjälä if (!engine || !engine->kernel_context) 459059f8782SVille Syrjälä return ERR_PTR(-ENOENT); 460059f8782SVille Syrjälä 461059f8782SVille Syrjälä overlay = kzalloc_obj(*overlay); 462059f8782SVille Syrjälä if (!overlay) 463059f8782SVille Syrjälä return ERR_PTR(-ENOMEM); 464059f8782SVille Syrjälä 465059f8782SVille Syrjälä overlay->i915 = i915; 466059f8782SVille Syrjälä overlay->context = engine->kernel_context; 467059f8782SVille Syrjälä 468059f8782SVille Syrjälä i915_active_init(&overlay->last_flip, 469059f8782SVille Syrjälä NULL, i915_overlay_last_flip_retire, 0); 470059f8782SVille Syrjälä 471059f8782SVille Syrjälä ret = get_registers(overlay, needs_physical); 472059f8782SVille Syrjälä if (ret) { 473059f8782SVille Syrjälä kfree(overlay); 474059f8782SVille Syrjälä return ERR_PTR(ret); 475059f8782SVille Syrjälä } 476059f8782SVille Syrjälä 477059f8782SVille Syrjälä i915->overlay = overlay; 478059f8782SVille Syrjälä 479059f8782SVille Syrjälä return overlay->regs; 480059f8782SVille Syrjälä } 481059f8782SVille Syrjälä 482e3f33adfSVille Syrjälä static void i915_overlay_cleanup(struct drm_device *drm) 483059f8782SVille Syrjälä { 484059f8782SVille Syrjälä struct drm_i915_private *i915 = to_i915(drm); 485aa029f7aSVille Syrjälä struct i915_overlay *overlay = i915->overlay; 486059f8782SVille Syrjälä 487059f8782SVille Syrjälä if (!overlay) 488059f8782SVille Syrjälä return; 489059f8782SVille Syrjälä 490059f8782SVille Syrjälä /* 491059f8782SVille Syrjälä * The bo's should be free'd by the generic code already. 492059f8782SVille Syrjälä * Furthermore modesetting teardown happens beforehand so the 493059f8782SVille Syrjälä * hardware should be off already. 494059f8782SVille Syrjälä */ 495059f8782SVille Syrjälä drm_WARN_ON(drm, i915_overlay_is_active(drm)); 496059f8782SVille Syrjälä 497059f8782SVille Syrjälä i915_gem_object_put(overlay->reg_bo); 498059f8782SVille Syrjälä i915_active_fini(&overlay->last_flip); 499059f8782SVille Syrjälä 500059f8782SVille Syrjälä kfree(overlay); 501aa029f7aSVille Syrjälä i915->overlay = NULL; 502059f8782SVille Syrjälä } 503e3f33adfSVille Syrjälä 504e3f33adfSVille Syrjälä const struct intel_display_overlay_interface i915_display_overlay_interface = { 505e3f33adfSVille Syrjälä .is_active = i915_overlay_is_active, 506e3f33adfSVille Syrjälä .overlay_on = i915_overlay_on, 507e3f33adfSVille Syrjälä .overlay_continue = i915_overlay_continue, 508e3f33adfSVille Syrjälä .overlay_off = i915_overlay_off, 509e3f33adfSVille Syrjälä .recover_from_interrupt = i915_overlay_recover_from_interrupt, 510e3f33adfSVille Syrjälä .release_old_vid = i915_overlay_release_old_vid, 511e3f33adfSVille Syrjälä .reset = i915_overlay_reset, 512e3f33adfSVille Syrjälä .obj_lookup = i915_overlay_obj_lookup, 513e3f33adfSVille Syrjälä .pin_fb = i915_overlay_pin_fb, 514e3f33adfSVille Syrjälä .unpin_fb = i915_overlay_unpin_fb, 515e3f33adfSVille Syrjälä .setup = i915_overlay_setup, 516e3f33adfSVille Syrjälä .cleanup = i915_overlay_cleanup, 517e3f33adfSVille Syrjälä }; 518