1 1.3 riastrad /* $NetBSD: intel_overlay.c,v 1.3 2021/12/19 11:48:02 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2009 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 8 1.1 riastrad * to deal in the Software without restriction, including without limitation 9 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 11 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 12 1.1 riastrad * 13 1.1 riastrad * The above copyright notice and this permission notice (including the next 14 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 15 1.1 riastrad * Software. 16 1.1 riastrad * 17 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 1.1 riastrad * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 1.1 riastrad * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 1.1 riastrad * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 1.1 riastrad * SOFTWARE. 24 1.1 riastrad * 25 1.1 riastrad * Authors: 26 1.1 riastrad * Daniel Vetter <daniel (at) ffwll.ch> 27 1.1 riastrad * 28 1.1 riastrad * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c 29 1.1 riastrad */ 30 1.1 riastrad 31 1.1 riastrad #include <sys/cdefs.h> 32 1.3 riastrad __KERNEL_RCSID(0, "$NetBSD: intel_overlay.c,v 1.3 2021/12/19 11:48:02 riastradh Exp $"); 33 1.1 riastrad 34 1.1 riastrad #include <drm/drm_fourcc.h> 35 1.1 riastrad #include <drm/i915_drm.h> 36 1.1 riastrad 37 1.1 riastrad #include "gem/i915_gem_pm.h" 38 1.1 riastrad #include "gt/intel_ring.h" 39 1.1 riastrad 40 1.1 riastrad #include "i915_drv.h" 41 1.1 riastrad #include "i915_reg.h" 42 1.1 riastrad #include "intel_display_types.h" 43 1.1 riastrad #include "intel_frontbuffer.h" 44 1.1 riastrad #include "intel_overlay.h" 45 1.1 riastrad 46 1.3 riastrad #include <linux/nbsd-namespace.h> 47 1.3 riastrad 48 1.1 riastrad /* Limits for overlay size. According to intel doc, the real limits are: 49 1.1 riastrad * Y width: 4095, UV width (planar): 2047, Y height: 2047, 50 1.1 riastrad * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use 51 1.1 riastrad * the mininum of both. */ 52 1.1 riastrad #define IMAGE_MAX_WIDTH 2048 53 1.1 riastrad #define IMAGE_MAX_HEIGHT 2046 /* 2 * 1023 */ 54 1.1 riastrad /* on 830 and 845 these large limits result in the card hanging */ 55 1.1 riastrad #define IMAGE_MAX_WIDTH_LEGACY 1024 56 1.1 riastrad #define IMAGE_MAX_HEIGHT_LEGACY 1088 57 1.1 riastrad 58 1.1 riastrad /* overlay register definitions */ 59 1.1 riastrad /* OCMD register */ 60 1.1 riastrad #define OCMD_TILED_SURFACE (0x1<<19) 61 1.1 riastrad #define OCMD_MIRROR_MASK (0x3<<17) 62 1.1 riastrad #define OCMD_MIRROR_MODE (0x3<<17) 63 1.1 riastrad #define OCMD_MIRROR_HORIZONTAL (0x1<<17) 64 1.1 riastrad #define OCMD_MIRROR_VERTICAL (0x2<<17) 65 1.1 riastrad #define OCMD_MIRROR_BOTH (0x3<<17) 66 1.1 riastrad #define OCMD_BYTEORDER_MASK (0x3<<14) /* zero for YUYV or FOURCC YUY2 */ 67 1.1 riastrad #define OCMD_UV_SWAP (0x1<<14) /* YVYU */ 68 1.1 riastrad #define OCMD_Y_SWAP (0x2<<14) /* UYVY or FOURCC UYVY */ 69 1.1 riastrad #define OCMD_Y_AND_UV_SWAP (0x3<<14) /* VYUY */ 70 1.1 riastrad #define OCMD_SOURCE_FORMAT_MASK (0xf<<10) 71 1.1 riastrad #define OCMD_RGB_888 (0x1<<10) /* not in i965 Intel docs */ 72 1.1 riastrad #define OCMD_RGB_555 (0x2<<10) /* not in i965 Intel docs */ 73 1.1 riastrad #define OCMD_RGB_565 (0x3<<10) /* not in i965 Intel docs */ 74 1.1 riastrad #define OCMD_YUV_422_PACKED (0x8<<10) 75 1.1 riastrad #define OCMD_YUV_411_PACKED (0x9<<10) /* not in i965 Intel docs */ 76 1.1 riastrad #define OCMD_YUV_420_PLANAR (0xc<<10) 77 1.1 riastrad #define OCMD_YUV_422_PLANAR (0xd<<10) 78 1.1 riastrad #define OCMD_YUV_410_PLANAR (0xe<<10) /* also 411 */ 79 1.1 riastrad #define OCMD_TVSYNCFLIP_PARITY (0x1<<9) 80 1.1 riastrad #define OCMD_TVSYNCFLIP_ENABLE (0x1<<7) 81 1.1 riastrad #define OCMD_BUF_TYPE_MASK (0x1<<5) 82 1.1 riastrad #define OCMD_BUF_TYPE_FRAME (0x0<<5) 83 1.1 riastrad #define OCMD_BUF_TYPE_FIELD (0x1<<5) 84 1.1 riastrad #define OCMD_TEST_MODE (0x1<<4) 85 1.1 riastrad #define OCMD_BUFFER_SELECT (0x3<<2) 86 1.1 riastrad #define OCMD_BUFFER0 (0x0<<2) 87 1.1 riastrad #define OCMD_BUFFER1 (0x1<<2) 88 1.1 riastrad #define OCMD_FIELD_SELECT (0x1<<2) 89 1.1 riastrad #define OCMD_FIELD0 (0x0<<1) 90 1.1 riastrad #define OCMD_FIELD1 (0x1<<1) 91 1.1 riastrad #define OCMD_ENABLE (0x1<<0) 92 1.1 riastrad 93 1.1 riastrad /* OCONFIG register */ 94 1.1 riastrad #define OCONF_PIPE_MASK (0x1<<18) 95 1.1 riastrad #define OCONF_PIPE_A (0x0<<18) 96 1.1 riastrad #define OCONF_PIPE_B (0x1<<18) 97 1.1 riastrad #define OCONF_GAMMA2_ENABLE (0x1<<16) 98 1.1 riastrad #define OCONF_CSC_MODE_BT601 (0x0<<5) 99 1.1 riastrad #define OCONF_CSC_MODE_BT709 (0x1<<5) 100 1.1 riastrad #define OCONF_CSC_BYPASS (0x1<<4) 101 1.1 riastrad #define OCONF_CC_OUT_8BIT (0x1<<3) 102 1.1 riastrad #define OCONF_TEST_MODE (0x1<<2) 103 1.1 riastrad #define OCONF_THREE_LINE_BUFFER (0x1<<0) 104 1.1 riastrad #define OCONF_TWO_LINE_BUFFER (0x0<<0) 105 1.1 riastrad 106 1.1 riastrad /* DCLRKM (dst-key) register */ 107 1.1 riastrad #define DST_KEY_ENABLE (0x1<<31) 108 1.1 riastrad #define CLK_RGB24_MASK 0x0 109 1.1 riastrad #define CLK_RGB16_MASK 0x070307 110 1.1 riastrad #define CLK_RGB15_MASK 0x070707 111 1.1 riastrad #define CLK_RGB8I_MASK 0xffffff 112 1.1 riastrad 113 1.1 riastrad #define RGB16_TO_COLORKEY(c) \ 114 1.1 riastrad (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) 115 1.1 riastrad #define RGB15_TO_COLORKEY(c) \ 116 1.1 riastrad (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) 117 1.1 riastrad 118 1.1 riastrad /* overlay flip addr flag */ 119 1.1 riastrad #define OFC_UPDATE 0x1 120 1.1 riastrad 121 1.1 riastrad /* polyphase filter coefficients */ 122 1.1 riastrad #define N_HORIZ_Y_TAPS 5 123 1.1 riastrad #define N_VERT_Y_TAPS 3 124 1.1 riastrad #define N_HORIZ_UV_TAPS 3 125 1.1 riastrad #define N_VERT_UV_TAPS 3 126 1.1 riastrad #define N_PHASES 17 127 1.1 riastrad #define MAX_TAPS 5 128 1.1 riastrad 129 1.1 riastrad /* memory bufferd overlay registers */ 130 1.1 riastrad struct overlay_registers { 131 1.1 riastrad u32 OBUF_0Y; 132 1.1 riastrad u32 OBUF_1Y; 133 1.1 riastrad u32 OBUF_0U; 134 1.1 riastrad u32 OBUF_0V; 135 1.1 riastrad u32 OBUF_1U; 136 1.1 riastrad u32 OBUF_1V; 137 1.1 riastrad u32 OSTRIDE; 138 1.1 riastrad u32 YRGB_VPH; 139 1.1 riastrad u32 UV_VPH; 140 1.1 riastrad u32 HORZ_PH; 141 1.1 riastrad u32 INIT_PHS; 142 1.1 riastrad u32 DWINPOS; 143 1.1 riastrad u32 DWINSZ; 144 1.1 riastrad u32 SWIDTH; 145 1.1 riastrad u32 SWIDTHSW; 146 1.1 riastrad u32 SHEIGHT; 147 1.1 riastrad u32 YRGBSCALE; 148 1.1 riastrad u32 UVSCALE; 149 1.1 riastrad u32 OCLRC0; 150 1.1 riastrad u32 OCLRC1; 151 1.1 riastrad u32 DCLRKV; 152 1.1 riastrad u32 DCLRKM; 153 1.1 riastrad u32 SCLRKVH; 154 1.1 riastrad u32 SCLRKVL; 155 1.1 riastrad u32 SCLRKEN; 156 1.1 riastrad u32 OCONFIG; 157 1.1 riastrad u32 OCMD; 158 1.1 riastrad u32 RESERVED1; /* 0x6C */ 159 1.1 riastrad u32 OSTART_0Y; 160 1.1 riastrad u32 OSTART_1Y; 161 1.1 riastrad u32 OSTART_0U; 162 1.1 riastrad u32 OSTART_0V; 163 1.1 riastrad u32 OSTART_1U; 164 1.1 riastrad u32 OSTART_1V; 165 1.1 riastrad u32 OTILEOFF_0Y; 166 1.1 riastrad u32 OTILEOFF_1Y; 167 1.1 riastrad u32 OTILEOFF_0U; 168 1.1 riastrad u32 OTILEOFF_0V; 169 1.1 riastrad u32 OTILEOFF_1U; 170 1.1 riastrad u32 OTILEOFF_1V; 171 1.1 riastrad u32 FASTHSCALE; /* 0xA0 */ 172 1.1 riastrad u32 UVSCALEV; /* 0xA4 */ 173 1.1 riastrad u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */ 174 1.1 riastrad u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */ 175 1.1 riastrad u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES]; 176 1.1 riastrad u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */ 177 1.1 riastrad u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES]; 178 1.1 riastrad u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */ 179 1.1 riastrad u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES]; 180 1.1 riastrad u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */ 181 1.1 riastrad u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; 182 1.1 riastrad }; 183 1.1 riastrad 184 1.2 riastrad #ifdef __NetBSD__ /* XXX intel overlay iomem */ 185 1.2 riastrad # define __intel_overlay_iomem 186 1.2 riastrad # define __iomem __intel_overlay_iomem 187 1.2 riastrad 188 1.2 riastrad static inline void 189 1.2 riastrad iowrite32(uint32_t value, uint32_t __intel_overlay_iomem *ptr) 190 1.2 riastrad { 191 1.2 riastrad 192 1.2 riastrad __insn_barrier(); 193 1.2 riastrad *ptr = value; 194 1.2 riastrad } 195 1.2 riastrad #endif 196 1.2 riastrad 197 1.1 riastrad struct intel_overlay { 198 1.1 riastrad struct drm_i915_private *i915; 199 1.1 riastrad struct intel_context *context; 200 1.1 riastrad struct intel_crtc *crtc; 201 1.1 riastrad struct i915_vma *vma; 202 1.1 riastrad struct i915_vma *old_vma; 203 1.1 riastrad bool active; 204 1.1 riastrad bool pfit_active; 205 1.1 riastrad u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ 206 1.1 riastrad u32 color_key:24; 207 1.1 riastrad u32 color_key_enabled:1; 208 1.1 riastrad u32 brightness, contrast, saturation; 209 1.1 riastrad u32 old_xscale, old_yscale; 210 1.1 riastrad /* register access */ 211 1.1 riastrad struct drm_i915_gem_object *reg_bo; 212 1.1 riastrad struct overlay_registers __iomem *regs; 213 1.1 riastrad u32 flip_addr; 214 1.1 riastrad /* flip handling */ 215 1.1 riastrad struct i915_active last_flip; 216 1.1 riastrad void (*flip_complete)(struct intel_overlay *ovl); 217 1.1 riastrad }; 218 1.1 riastrad 219 1.1 riastrad static void i830_overlay_clock_gating(struct drm_i915_private *dev_priv, 220 1.1 riastrad bool enable) 221 1.1 riastrad { 222 1.1 riastrad struct pci_dev *pdev = dev_priv->drm.pdev; 223 1.1 riastrad u8 val; 224 1.1 riastrad 225 1.1 riastrad /* WA_OVERLAY_CLKGATE:alm */ 226 1.1 riastrad if (enable) 227 1.1 riastrad I915_WRITE(DSPCLK_GATE_D, 0); 228 1.1 riastrad else 229 1.1 riastrad I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); 230 1.1 riastrad 231 1.1 riastrad /* WA_DISABLE_L2CACHE_CLOCK_GATING:alm */ 232 1.1 riastrad pci_bus_read_config_byte(pdev->bus, 233 1.1 riastrad PCI_DEVFN(0, 0), I830_CLOCK_GATE, &val); 234 1.1 riastrad if (enable) 235 1.1 riastrad val &= ~I830_L2_CACHE_CLOCK_GATE_DISABLE; 236 1.1 riastrad else 237 1.1 riastrad val |= I830_L2_CACHE_CLOCK_GATE_DISABLE; 238 1.1 riastrad pci_bus_write_config_byte(pdev->bus, 239 1.1 riastrad PCI_DEVFN(0, 0), I830_CLOCK_GATE, val); 240 1.1 riastrad } 241 1.1 riastrad 242 1.1 riastrad static struct i915_request * 243 1.1 riastrad alloc_request(struct intel_overlay *overlay, void (*fn)(struct intel_overlay *)) 244 1.1 riastrad { 245 1.1 riastrad struct i915_request *rq; 246 1.1 riastrad int err; 247 1.1 riastrad 248 1.1 riastrad overlay->flip_complete = fn; 249 1.1 riastrad 250 1.1 riastrad rq = i915_request_create(overlay->context); 251 1.1 riastrad if (IS_ERR(rq)) 252 1.1 riastrad return rq; 253 1.1 riastrad 254 1.1 riastrad err = i915_active_add_request(&overlay->last_flip, rq); 255 1.1 riastrad if (err) { 256 1.1 riastrad i915_request_add(rq); 257 1.1 riastrad return ERR_PTR(err); 258 1.1 riastrad } 259 1.1 riastrad 260 1.1 riastrad return rq; 261 1.1 riastrad } 262 1.1 riastrad 263 1.1 riastrad /* overlay needs to be disable in OCMD reg */ 264 1.1 riastrad static int intel_overlay_on(struct intel_overlay *overlay) 265 1.1 riastrad { 266 1.1 riastrad struct drm_i915_private *dev_priv = overlay->i915; 267 1.1 riastrad struct i915_request *rq; 268 1.1 riastrad u32 *cs; 269 1.1 riastrad 270 1.1 riastrad WARN_ON(overlay->active); 271 1.1 riastrad 272 1.1 riastrad rq = alloc_request(overlay, NULL); 273 1.1 riastrad if (IS_ERR(rq)) 274 1.1 riastrad return PTR_ERR(rq); 275 1.1 riastrad 276 1.1 riastrad cs = intel_ring_begin(rq, 4); 277 1.1 riastrad if (IS_ERR(cs)) { 278 1.1 riastrad i915_request_add(rq); 279 1.1 riastrad return PTR_ERR(cs); 280 1.1 riastrad } 281 1.1 riastrad 282 1.1 riastrad overlay->active = true; 283 1.1 riastrad 284 1.1 riastrad if (IS_I830(dev_priv)) 285 1.1 riastrad i830_overlay_clock_gating(dev_priv, false); 286 1.1 riastrad 287 1.1 riastrad *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_ON; 288 1.1 riastrad *cs++ = overlay->flip_addr | OFC_UPDATE; 289 1.1 riastrad *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP; 290 1.1 riastrad *cs++ = MI_NOOP; 291 1.1 riastrad intel_ring_advance(rq, cs); 292 1.1 riastrad 293 1.1 riastrad i915_request_add(rq); 294 1.1 riastrad 295 1.1 riastrad return i915_active_wait(&overlay->last_flip); 296 1.1 riastrad } 297 1.1 riastrad 298 1.1 riastrad static void intel_overlay_flip_prepare(struct intel_overlay *overlay, 299 1.1 riastrad struct i915_vma *vma) 300 1.1 riastrad { 301 1.1 riastrad enum pipe pipe = overlay->crtc->pipe; 302 1.1 riastrad struct intel_frontbuffer *from = NULL, *to = NULL; 303 1.1 riastrad 304 1.1 riastrad WARN_ON(overlay->old_vma); 305 1.1 riastrad 306 1.1 riastrad if (overlay->vma) 307 1.1 riastrad from = intel_frontbuffer_get(overlay->vma->obj); 308 1.1 riastrad if (vma) 309 1.1 riastrad to = intel_frontbuffer_get(vma->obj); 310 1.1 riastrad 311 1.1 riastrad intel_frontbuffer_track(from, to, INTEL_FRONTBUFFER_OVERLAY(pipe)); 312 1.1 riastrad 313 1.1 riastrad if (to) 314 1.1 riastrad intel_frontbuffer_put(to); 315 1.1 riastrad if (from) 316 1.1 riastrad intel_frontbuffer_put(from); 317 1.1 riastrad 318 1.1 riastrad intel_frontbuffer_flip_prepare(overlay->i915, 319 1.1 riastrad INTEL_FRONTBUFFER_OVERLAY(pipe)); 320 1.1 riastrad 321 1.1 riastrad overlay->old_vma = overlay->vma; 322 1.1 riastrad if (vma) 323 1.1 riastrad overlay->vma = i915_vma_get(vma); 324 1.1 riastrad else 325 1.1 riastrad overlay->vma = NULL; 326 1.1 riastrad } 327 1.1 riastrad 328 1.1 riastrad /* overlay needs to be enabled in OCMD reg */ 329 1.1 riastrad static int intel_overlay_continue(struct intel_overlay *overlay, 330 1.1 riastrad struct i915_vma *vma, 331 1.1 riastrad bool load_polyphase_filter) 332 1.1 riastrad { 333 1.1 riastrad struct drm_i915_private *dev_priv = overlay->i915; 334 1.1 riastrad struct i915_request *rq; 335 1.1 riastrad u32 flip_addr = overlay->flip_addr; 336 1.1 riastrad u32 tmp, *cs; 337 1.1 riastrad 338 1.1 riastrad WARN_ON(!overlay->active); 339 1.1 riastrad 340 1.1 riastrad if (load_polyphase_filter) 341 1.1 riastrad flip_addr |= OFC_UPDATE; 342 1.1 riastrad 343 1.1 riastrad /* check for underruns */ 344 1.1 riastrad tmp = I915_READ(DOVSTA); 345 1.1 riastrad if (tmp & (1 << 17)) 346 1.1 riastrad DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); 347 1.1 riastrad 348 1.1 riastrad rq = alloc_request(overlay, NULL); 349 1.1 riastrad if (IS_ERR(rq)) 350 1.1 riastrad return PTR_ERR(rq); 351 1.1 riastrad 352 1.1 riastrad cs = intel_ring_begin(rq, 2); 353 1.1 riastrad if (IS_ERR(cs)) { 354 1.1 riastrad i915_request_add(rq); 355 1.1 riastrad return PTR_ERR(cs); 356 1.1 riastrad } 357 1.1 riastrad 358 1.1 riastrad *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE; 359 1.1 riastrad *cs++ = flip_addr; 360 1.1 riastrad intel_ring_advance(rq, cs); 361 1.1 riastrad 362 1.1 riastrad intel_overlay_flip_prepare(overlay, vma); 363 1.1 riastrad i915_request_add(rq); 364 1.1 riastrad 365 1.1 riastrad return 0; 366 1.1 riastrad } 367 1.1 riastrad 368 1.1 riastrad static void intel_overlay_release_old_vma(struct intel_overlay *overlay) 369 1.1 riastrad { 370 1.1 riastrad struct i915_vma *vma; 371 1.1 riastrad 372 1.1 riastrad vma = fetch_and_zero(&overlay->old_vma); 373 1.1 riastrad if (WARN_ON(!vma)) 374 1.1 riastrad return; 375 1.1 riastrad 376 1.1 riastrad intel_frontbuffer_flip_complete(overlay->i915, 377 1.1 riastrad INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe)); 378 1.1 riastrad 379 1.1 riastrad i915_gem_object_unpin_from_display_plane(vma); 380 1.1 riastrad i915_vma_put(vma); 381 1.1 riastrad } 382 1.1 riastrad 383 1.1 riastrad static void 384 1.1 riastrad intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) 385 1.1 riastrad { 386 1.1 riastrad intel_overlay_release_old_vma(overlay); 387 1.1 riastrad } 388 1.1 riastrad 389 1.1 riastrad static void intel_overlay_off_tail(struct intel_overlay *overlay) 390 1.1 riastrad { 391 1.1 riastrad struct drm_i915_private *dev_priv = overlay->i915; 392 1.1 riastrad 393 1.1 riastrad intel_overlay_release_old_vma(overlay); 394 1.1 riastrad 395 1.1 riastrad overlay->crtc->overlay = NULL; 396 1.1 riastrad overlay->crtc = NULL; 397 1.1 riastrad overlay->active = false; 398 1.1 riastrad 399 1.1 riastrad if (IS_I830(dev_priv)) 400 1.1 riastrad i830_overlay_clock_gating(dev_priv, true); 401 1.1 riastrad } 402 1.1 riastrad 403 1.1 riastrad static void 404 1.1 riastrad intel_overlay_last_flip_retire(struct i915_active *active) 405 1.1 riastrad { 406 1.1 riastrad struct intel_overlay *overlay = 407 1.1 riastrad container_of(active, typeof(*overlay), last_flip); 408 1.1 riastrad 409 1.1 riastrad if (overlay->flip_complete) 410 1.1 riastrad overlay->flip_complete(overlay); 411 1.1 riastrad } 412 1.1 riastrad 413 1.1 riastrad /* overlay needs to be disabled in OCMD reg */ 414 1.1 riastrad static int intel_overlay_off(struct intel_overlay *overlay) 415 1.1 riastrad { 416 1.1 riastrad struct i915_request *rq; 417 1.1 riastrad u32 *cs, flip_addr = overlay->flip_addr; 418 1.1 riastrad 419 1.1 riastrad WARN_ON(!overlay->active); 420 1.1 riastrad 421 1.1 riastrad /* According to intel docs the overlay hw may hang (when switching 422 1.1 riastrad * off) without loading the filter coeffs. It is however unclear whether 423 1.1 riastrad * this applies to the disabling of the overlay or to the switching off 424 1.1 riastrad * of the hw. Do it in both cases */ 425 1.1 riastrad flip_addr |= OFC_UPDATE; 426 1.1 riastrad 427 1.1 riastrad rq = alloc_request(overlay, intel_overlay_off_tail); 428 1.1 riastrad if (IS_ERR(rq)) 429 1.1 riastrad return PTR_ERR(rq); 430 1.1 riastrad 431 1.1 riastrad cs = intel_ring_begin(rq, 6); 432 1.1 riastrad if (IS_ERR(cs)) { 433 1.1 riastrad i915_request_add(rq); 434 1.1 riastrad return PTR_ERR(cs); 435 1.1 riastrad } 436 1.1 riastrad 437 1.1 riastrad /* wait for overlay to go idle */ 438 1.1 riastrad *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE; 439 1.1 riastrad *cs++ = flip_addr; 440 1.1 riastrad *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP; 441 1.1 riastrad 442 1.1 riastrad /* turn overlay off */ 443 1.1 riastrad *cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_OFF; 444 1.1 riastrad *cs++ = flip_addr; 445 1.1 riastrad *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP; 446 1.1 riastrad 447 1.1 riastrad intel_ring_advance(rq, cs); 448 1.1 riastrad 449 1.1 riastrad intel_overlay_flip_prepare(overlay, NULL); 450 1.1 riastrad i915_request_add(rq); 451 1.1 riastrad 452 1.1 riastrad return i915_active_wait(&overlay->last_flip); 453 1.1 riastrad } 454 1.1 riastrad 455 1.1 riastrad /* recover from an interruption due to a signal 456 1.1 riastrad * We have to be careful not to repeat work forever an make forward progess. */ 457 1.1 riastrad static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) 458 1.1 riastrad { 459 1.1 riastrad return i915_active_wait(&overlay->last_flip); 460 1.1 riastrad } 461 1.1 riastrad 462 1.1 riastrad /* Wait for pending overlay flip and release old frame. 463 1.1 riastrad * Needs to be called before the overlay register are changed 464 1.1 riastrad * via intel_overlay_(un)map_regs 465 1.1 riastrad */ 466 1.1 riastrad static int intel_overlay_release_old_vid(struct intel_overlay *overlay) 467 1.1 riastrad { 468 1.1 riastrad struct drm_i915_private *dev_priv = overlay->i915; 469 1.1 riastrad struct i915_request *rq; 470 1.1 riastrad u32 *cs; 471 1.1 riastrad 472 1.1 riastrad /* 473 1.1 riastrad * Only wait if there is actually an old frame to release to 474 1.1 riastrad * guarantee forward progress. 475 1.1 riastrad */ 476 1.1 riastrad if (!overlay->old_vma) 477 1.1 riastrad return 0; 478 1.1 riastrad 479 1.1 riastrad if (!(I915_READ(GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) { 480 1.1 riastrad intel_overlay_release_old_vid_tail(overlay); 481 1.1 riastrad return 0; 482 1.1 riastrad } 483 1.1 riastrad 484 1.1 riastrad rq = alloc_request(overlay, intel_overlay_release_old_vid_tail); 485 1.1 riastrad if (IS_ERR(rq)) 486 1.1 riastrad return PTR_ERR(rq); 487 1.1 riastrad 488 1.1 riastrad cs = intel_ring_begin(rq, 2); 489 1.1 riastrad if (IS_ERR(cs)) { 490 1.1 riastrad i915_request_add(rq); 491 1.1 riastrad return PTR_ERR(cs); 492 1.1 riastrad } 493 1.1 riastrad 494 1.1 riastrad *cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP; 495 1.1 riastrad *cs++ = MI_NOOP; 496 1.1 riastrad intel_ring_advance(rq, cs); 497 1.1 riastrad 498 1.1 riastrad i915_request_add(rq); 499 1.1 riastrad 500 1.1 riastrad return i915_active_wait(&overlay->last_flip); 501 1.1 riastrad } 502 1.1 riastrad 503 1.1 riastrad void intel_overlay_reset(struct drm_i915_private *dev_priv) 504 1.1 riastrad { 505 1.1 riastrad struct intel_overlay *overlay = dev_priv->overlay; 506 1.1 riastrad 507 1.1 riastrad if (!overlay) 508 1.1 riastrad return; 509 1.1 riastrad 510 1.1 riastrad overlay->old_xscale = 0; 511 1.1 riastrad overlay->old_yscale = 0; 512 1.1 riastrad overlay->crtc = NULL; 513 1.1 riastrad overlay->active = false; 514 1.1 riastrad } 515 1.1 riastrad 516 1.1 riastrad static int packed_depth_bytes(u32 format) 517 1.1 riastrad { 518 1.1 riastrad switch (format & I915_OVERLAY_DEPTH_MASK) { 519 1.1 riastrad case I915_OVERLAY_YUV422: 520 1.1 riastrad return 4; 521 1.1 riastrad case I915_OVERLAY_YUV411: 522 1.1 riastrad /* return 6; not implemented */ 523 1.1 riastrad default: 524 1.1 riastrad return -EINVAL; 525 1.1 riastrad } 526 1.1 riastrad } 527 1.1 riastrad 528 1.1 riastrad static int packed_width_bytes(u32 format, short width) 529 1.1 riastrad { 530 1.1 riastrad switch (format & I915_OVERLAY_DEPTH_MASK) { 531 1.1 riastrad case I915_OVERLAY_YUV422: 532 1.1 riastrad return width << 1; 533 1.1 riastrad default: 534 1.1 riastrad return -EINVAL; 535 1.1 riastrad } 536 1.1 riastrad } 537 1.1 riastrad 538 1.1 riastrad static int uv_hsubsampling(u32 format) 539 1.1 riastrad { 540 1.1 riastrad switch (format & I915_OVERLAY_DEPTH_MASK) { 541 1.1 riastrad case I915_OVERLAY_YUV422: 542 1.1 riastrad case I915_OVERLAY_YUV420: 543 1.1 riastrad return 2; 544 1.1 riastrad case I915_OVERLAY_YUV411: 545 1.1 riastrad case I915_OVERLAY_YUV410: 546 1.1 riastrad return 4; 547 1.1 riastrad default: 548 1.1 riastrad return -EINVAL; 549 1.1 riastrad } 550 1.1 riastrad } 551 1.1 riastrad 552 1.1 riastrad static int uv_vsubsampling(u32 format) 553 1.1 riastrad { 554 1.1 riastrad switch (format & I915_OVERLAY_DEPTH_MASK) { 555 1.1 riastrad case I915_OVERLAY_YUV420: 556 1.1 riastrad case I915_OVERLAY_YUV410: 557 1.1 riastrad return 2; 558 1.1 riastrad case I915_OVERLAY_YUV422: 559 1.1 riastrad case I915_OVERLAY_YUV411: 560 1.1 riastrad return 1; 561 1.1 riastrad default: 562 1.1 riastrad return -EINVAL; 563 1.1 riastrad } 564 1.1 riastrad } 565 1.1 riastrad 566 1.1 riastrad static u32 calc_swidthsw(struct drm_i915_private *dev_priv, u32 offset, u32 width) 567 1.1 riastrad { 568 1.1 riastrad u32 sw; 569 1.1 riastrad 570 1.1 riastrad if (IS_GEN(dev_priv, 2)) 571 1.1 riastrad sw = ALIGN((offset & 31) + width, 32); 572 1.1 riastrad else 573 1.1 riastrad sw = ALIGN((offset & 63) + width, 64); 574 1.1 riastrad 575 1.1 riastrad if (sw == 0) 576 1.1 riastrad return 0; 577 1.1 riastrad 578 1.1 riastrad return (sw - 32) >> 3; 579 1.1 riastrad } 580 1.1 riastrad 581 1.1 riastrad static const u16 y_static_hcoeffs[N_PHASES][N_HORIZ_Y_TAPS] = { 582 1.1 riastrad [ 0] = { 0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0, }, 583 1.1 riastrad [ 1] = { 0x3000, 0xb500, 0x19d0, 0x1880, 0xb440, }, 584 1.1 riastrad [ 2] = { 0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0, }, 585 1.1 riastrad [ 3] = { 0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380, }, 586 1.1 riastrad [ 4] = { 0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320, }, 587 1.1 riastrad [ 5] = { 0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0, }, 588 1.1 riastrad [ 6] = { 0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260, }, 589 1.1 riastrad [ 7] = { 0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200, }, 590 1.1 riastrad [ 8] = { 0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0, }, 591 1.1 riastrad [ 9] = { 0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160, }, 592 1.1 riastrad [10] = { 0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120, }, 593 1.1 riastrad [11] = { 0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0, }, 594 1.1 riastrad [12] = { 0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0, }, 595 1.1 riastrad [13] = { 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, }, 596 1.1 riastrad [14] = { 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, }, 597 1.1 riastrad [15] = { 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, }, 598 1.1 riastrad [16] = { 0xb000, 0x3000, 0x0800, 0x3000, 0xb000, }, 599 1.1 riastrad }; 600 1.1 riastrad 601 1.1 riastrad static const u16 uv_static_hcoeffs[N_PHASES][N_HORIZ_UV_TAPS] = { 602 1.1 riastrad [ 0] = { 0x3000, 0x1800, 0x1800, }, 603 1.1 riastrad [ 1] = { 0xb000, 0x18d0, 0x2e60, }, 604 1.1 riastrad [ 2] = { 0xb000, 0x1990, 0x2ce0, }, 605 1.1 riastrad [ 3] = { 0xb020, 0x1a68, 0x2b40, }, 606 1.1 riastrad [ 4] = { 0xb040, 0x1b20, 0x29e0, }, 607 1.1 riastrad [ 5] = { 0xb060, 0x1bd8, 0x2880, }, 608 1.1 riastrad [ 6] = { 0xb080, 0x1c88, 0x3e60, }, 609 1.1 riastrad [ 7] = { 0xb0a0, 0x1d28, 0x3c00, }, 610 1.1 riastrad [ 8] = { 0xb0c0, 0x1db8, 0x39e0, }, 611 1.1 riastrad [ 9] = { 0xb0e0, 0x1e40, 0x37e0, }, 612 1.1 riastrad [10] = { 0xb100, 0x1eb8, 0x3620, }, 613 1.1 riastrad [11] = { 0xb100, 0x1f18, 0x34a0, }, 614 1.1 riastrad [12] = { 0xb100, 0x1f68, 0x3360, }, 615 1.1 riastrad [13] = { 0xb0e0, 0x1fa8, 0x3240, }, 616 1.1 riastrad [14] = { 0xb0c0, 0x1fe0, 0x3140, }, 617 1.1 riastrad [15] = { 0xb060, 0x1ff0, 0x30a0, }, 618 1.1 riastrad [16] = { 0x3000, 0x0800, 0x3000, }, 619 1.1 riastrad }; 620 1.1 riastrad 621 1.1 riastrad static void update_polyphase_filter(struct overlay_registers __iomem *regs) 622 1.1 riastrad { 623 1.1 riastrad memcpy_toio(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs)); 624 1.1 riastrad memcpy_toio(regs->UV_HCOEFS, uv_static_hcoeffs, 625 1.1 riastrad sizeof(uv_static_hcoeffs)); 626 1.1 riastrad } 627 1.1 riastrad 628 1.1 riastrad static bool update_scaling_factors(struct intel_overlay *overlay, 629 1.1 riastrad struct overlay_registers __iomem *regs, 630 1.1 riastrad struct drm_intel_overlay_put_image *params) 631 1.1 riastrad { 632 1.1 riastrad /* fixed point with a 12 bit shift */ 633 1.1 riastrad u32 xscale, yscale, xscale_UV, yscale_UV; 634 1.1 riastrad #define FP_SHIFT 12 635 1.1 riastrad #define FRACT_MASK 0xfff 636 1.1 riastrad bool scale_changed = false; 637 1.1 riastrad int uv_hscale = uv_hsubsampling(params->flags); 638 1.1 riastrad int uv_vscale = uv_vsubsampling(params->flags); 639 1.1 riastrad 640 1.1 riastrad if (params->dst_width > 1) 641 1.1 riastrad xscale = ((params->src_scan_width - 1) << FP_SHIFT) / 642 1.1 riastrad params->dst_width; 643 1.1 riastrad else 644 1.1 riastrad xscale = 1 << FP_SHIFT; 645 1.1 riastrad 646 1.1 riastrad if (params->dst_height > 1) 647 1.1 riastrad yscale = ((params->src_scan_height - 1) << FP_SHIFT) / 648 1.1 riastrad params->dst_height; 649 1.1 riastrad else 650 1.1 riastrad yscale = 1 << FP_SHIFT; 651 1.1 riastrad 652 1.1 riastrad /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ 653 1.1 riastrad xscale_UV = xscale/uv_hscale; 654 1.1 riastrad yscale_UV = yscale/uv_vscale; 655 1.1 riastrad /* make the Y scale to UV scale ratio an exact multiply */ 656 1.1 riastrad xscale = xscale_UV * uv_hscale; 657 1.1 riastrad yscale = yscale_UV * uv_vscale; 658 1.1 riastrad /*} else { 659 1.1 riastrad xscale_UV = 0; 660 1.1 riastrad yscale_UV = 0; 661 1.1 riastrad }*/ 662 1.1 riastrad 663 1.1 riastrad if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) 664 1.1 riastrad scale_changed = true; 665 1.1 riastrad overlay->old_xscale = xscale; 666 1.1 riastrad overlay->old_yscale = yscale; 667 1.1 riastrad 668 1.1 riastrad iowrite32(((yscale & FRACT_MASK) << 20) | 669 1.1 riastrad ((xscale >> FP_SHIFT) << 16) | 670 1.1 riastrad ((xscale & FRACT_MASK) << 3), 671 1.1 riastrad ®s->YRGBSCALE); 672 1.1 riastrad 673 1.1 riastrad iowrite32(((yscale_UV & FRACT_MASK) << 20) | 674 1.1 riastrad ((xscale_UV >> FP_SHIFT) << 16) | 675 1.1 riastrad ((xscale_UV & FRACT_MASK) << 3), 676 1.1 riastrad ®s->UVSCALE); 677 1.1 riastrad 678 1.1 riastrad iowrite32((((yscale >> FP_SHIFT) << 16) | 679 1.1 riastrad ((yscale_UV >> FP_SHIFT) << 0)), 680 1.1 riastrad ®s->UVSCALEV); 681 1.1 riastrad 682 1.1 riastrad if (scale_changed) 683 1.1 riastrad update_polyphase_filter(regs); 684 1.1 riastrad 685 1.1 riastrad return scale_changed; 686 1.1 riastrad } 687 1.1 riastrad 688 1.1 riastrad static void update_colorkey(struct intel_overlay *overlay, 689 1.1 riastrad struct overlay_registers __iomem *regs) 690 1.1 riastrad { 691 1.1 riastrad const struct intel_plane_state *state = 692 1.1 riastrad to_intel_plane_state(overlay->crtc->base.primary->state); 693 1.1 riastrad u32 key = overlay->color_key; 694 1.1 riastrad u32 format = 0; 695 1.1 riastrad u32 flags = 0; 696 1.1 riastrad 697 1.1 riastrad if (overlay->color_key_enabled) 698 1.1 riastrad flags |= DST_KEY_ENABLE; 699 1.1 riastrad 700 1.1 riastrad if (state->uapi.visible) 701 1.1 riastrad format = state->hw.fb->format->format; 702 1.1 riastrad 703 1.1 riastrad switch (format) { 704 1.1 riastrad case DRM_FORMAT_C8: 705 1.1 riastrad key = 0; 706 1.1 riastrad flags |= CLK_RGB8I_MASK; 707 1.1 riastrad break; 708 1.1 riastrad case DRM_FORMAT_XRGB1555: 709 1.1 riastrad key = RGB15_TO_COLORKEY(key); 710 1.1 riastrad flags |= CLK_RGB15_MASK; 711 1.1 riastrad break; 712 1.1 riastrad case DRM_FORMAT_RGB565: 713 1.1 riastrad key = RGB16_TO_COLORKEY(key); 714 1.1 riastrad flags |= CLK_RGB16_MASK; 715 1.1 riastrad break; 716 1.1 riastrad default: 717 1.1 riastrad flags |= CLK_RGB24_MASK; 718 1.1 riastrad break; 719 1.1 riastrad } 720 1.1 riastrad 721 1.1 riastrad iowrite32(key, ®s->DCLRKV); 722 1.1 riastrad iowrite32(flags, ®s->DCLRKM); 723 1.1 riastrad } 724 1.1 riastrad 725 1.1 riastrad static u32 overlay_cmd_reg(struct drm_intel_overlay_put_image *params) 726 1.1 riastrad { 727 1.1 riastrad u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0; 728 1.1 riastrad 729 1.1 riastrad if (params->flags & I915_OVERLAY_YUV_PLANAR) { 730 1.1 riastrad switch (params->flags & I915_OVERLAY_DEPTH_MASK) { 731 1.1 riastrad case I915_OVERLAY_YUV422: 732 1.1 riastrad cmd |= OCMD_YUV_422_PLANAR; 733 1.1 riastrad break; 734 1.1 riastrad case I915_OVERLAY_YUV420: 735 1.1 riastrad cmd |= OCMD_YUV_420_PLANAR; 736 1.1 riastrad break; 737 1.1 riastrad case I915_OVERLAY_YUV411: 738 1.1 riastrad case I915_OVERLAY_YUV410: 739 1.1 riastrad cmd |= OCMD_YUV_410_PLANAR; 740 1.1 riastrad break; 741 1.1 riastrad } 742 1.1 riastrad } else { /* YUV packed */ 743 1.1 riastrad switch (params->flags & I915_OVERLAY_DEPTH_MASK) { 744 1.1 riastrad case I915_OVERLAY_YUV422: 745 1.1 riastrad cmd |= OCMD_YUV_422_PACKED; 746 1.1 riastrad break; 747 1.1 riastrad case I915_OVERLAY_YUV411: 748 1.1 riastrad cmd |= OCMD_YUV_411_PACKED; 749 1.1 riastrad break; 750 1.1 riastrad } 751 1.1 riastrad 752 1.1 riastrad switch (params->flags & I915_OVERLAY_SWAP_MASK) { 753 1.1 riastrad case I915_OVERLAY_NO_SWAP: 754 1.1 riastrad break; 755 1.1 riastrad case I915_OVERLAY_UV_SWAP: 756 1.1 riastrad cmd |= OCMD_UV_SWAP; 757 1.1 riastrad break; 758 1.1 riastrad case I915_OVERLAY_Y_SWAP: 759 1.1 riastrad cmd |= OCMD_Y_SWAP; 760 1.1 riastrad break; 761 1.1 riastrad case I915_OVERLAY_Y_AND_UV_SWAP: 762 1.1 riastrad cmd |= OCMD_Y_AND_UV_SWAP; 763 1.1 riastrad break; 764 1.1 riastrad } 765 1.1 riastrad } 766 1.1 riastrad 767 1.1 riastrad return cmd; 768 1.1 riastrad } 769 1.1 riastrad 770 1.1 riastrad static int intel_overlay_do_put_image(struct intel_overlay *overlay, 771 1.1 riastrad struct drm_i915_gem_object *new_bo, 772 1.1 riastrad struct drm_intel_overlay_put_image *params) 773 1.1 riastrad { 774 1.1 riastrad struct overlay_registers __iomem *regs = overlay->regs; 775 1.1 riastrad struct drm_i915_private *dev_priv = overlay->i915; 776 1.1 riastrad u32 swidth, swidthsw, sheight, ostride; 777 1.1 riastrad enum pipe pipe = overlay->crtc->pipe; 778 1.1 riastrad bool scale_changed = false; 779 1.1 riastrad struct i915_vma *vma; 780 1.1 riastrad int ret, tmp_width; 781 1.1 riastrad 782 1.1 riastrad WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); 783 1.1 riastrad 784 1.1 riastrad ret = intel_overlay_release_old_vid(overlay); 785 1.1 riastrad if (ret != 0) 786 1.1 riastrad return ret; 787 1.1 riastrad 788 1.1 riastrad atomic_inc(&dev_priv->gpu_error.pending_fb_pin); 789 1.1 riastrad 790 1.1 riastrad vma = i915_gem_object_pin_to_display_plane(new_bo, 791 1.1 riastrad 0, NULL, PIN_MAPPABLE); 792 1.1 riastrad if (IS_ERR(vma)) { 793 1.1 riastrad ret = PTR_ERR(vma); 794 1.1 riastrad goto out_pin_section; 795 1.1 riastrad } 796 1.1 riastrad i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB); 797 1.1 riastrad 798 1.1 riastrad if (!overlay->active) { 799 1.1 riastrad u32 oconfig; 800 1.1 riastrad 801 1.1 riastrad oconfig = OCONF_CC_OUT_8BIT; 802 1.1 riastrad if (IS_GEN(dev_priv, 4)) 803 1.1 riastrad oconfig |= OCONF_CSC_MODE_BT709; 804 1.1 riastrad oconfig |= pipe == 0 ? 805 1.1 riastrad OCONF_PIPE_A : OCONF_PIPE_B; 806 1.1 riastrad iowrite32(oconfig, ®s->OCONFIG); 807 1.1 riastrad 808 1.1 riastrad ret = intel_overlay_on(overlay); 809 1.1 riastrad if (ret != 0) 810 1.1 riastrad goto out_unpin; 811 1.1 riastrad } 812 1.1 riastrad 813 1.1 riastrad iowrite32(params->dst_y << 16 | params->dst_x, ®s->DWINPOS); 814 1.1 riastrad iowrite32(params->dst_height << 16 | params->dst_width, ®s->DWINSZ); 815 1.1 riastrad 816 1.1 riastrad if (params->flags & I915_OVERLAY_YUV_PACKED) 817 1.1 riastrad tmp_width = packed_width_bytes(params->flags, 818 1.1 riastrad params->src_width); 819 1.1 riastrad else 820 1.1 riastrad tmp_width = params->src_width; 821 1.1 riastrad 822 1.1 riastrad swidth = params->src_width; 823 1.1 riastrad swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width); 824 1.1 riastrad sheight = params->src_height; 825 1.1 riastrad iowrite32(i915_ggtt_offset(vma) + params->offset_Y, ®s->OBUF_0Y); 826 1.1 riastrad ostride = params->stride_Y; 827 1.1 riastrad 828 1.1 riastrad if (params->flags & I915_OVERLAY_YUV_PLANAR) { 829 1.1 riastrad int uv_hscale = uv_hsubsampling(params->flags); 830 1.1 riastrad int uv_vscale = uv_vsubsampling(params->flags); 831 1.1 riastrad u32 tmp_U, tmp_V; 832 1.1 riastrad 833 1.1 riastrad swidth |= (params->src_width / uv_hscale) << 16; 834 1.1 riastrad sheight |= (params->src_height / uv_vscale) << 16; 835 1.1 riastrad 836 1.1 riastrad tmp_U = calc_swidthsw(dev_priv, params->offset_U, 837 1.1 riastrad params->src_width / uv_hscale); 838 1.1 riastrad tmp_V = calc_swidthsw(dev_priv, params->offset_V, 839 1.1 riastrad params->src_width / uv_hscale); 840 1.1 riastrad swidthsw |= max(tmp_U, tmp_V) << 16; 841 1.1 riastrad 842 1.1 riastrad iowrite32(i915_ggtt_offset(vma) + params->offset_U, 843 1.1 riastrad ®s->OBUF_0U); 844 1.1 riastrad iowrite32(i915_ggtt_offset(vma) + params->offset_V, 845 1.1 riastrad ®s->OBUF_0V); 846 1.1 riastrad 847 1.1 riastrad ostride |= params->stride_UV << 16; 848 1.1 riastrad } 849 1.1 riastrad 850 1.1 riastrad iowrite32(swidth, ®s->SWIDTH); 851 1.1 riastrad iowrite32(swidthsw, ®s->SWIDTHSW); 852 1.1 riastrad iowrite32(sheight, ®s->SHEIGHT); 853 1.1 riastrad iowrite32(ostride, ®s->OSTRIDE); 854 1.1 riastrad 855 1.1 riastrad scale_changed = update_scaling_factors(overlay, regs, params); 856 1.1 riastrad 857 1.1 riastrad update_colorkey(overlay, regs); 858 1.1 riastrad 859 1.1 riastrad iowrite32(overlay_cmd_reg(params), ®s->OCMD); 860 1.1 riastrad 861 1.1 riastrad ret = intel_overlay_continue(overlay, vma, scale_changed); 862 1.1 riastrad if (ret) 863 1.1 riastrad goto out_unpin; 864 1.1 riastrad 865 1.1 riastrad return 0; 866 1.1 riastrad 867 1.1 riastrad out_unpin: 868 1.1 riastrad i915_gem_object_unpin_from_display_plane(vma); 869 1.1 riastrad out_pin_section: 870 1.1 riastrad atomic_dec(&dev_priv->gpu_error.pending_fb_pin); 871 1.1 riastrad 872 1.1 riastrad return ret; 873 1.1 riastrad } 874 1.1 riastrad 875 1.1 riastrad int intel_overlay_switch_off(struct intel_overlay *overlay) 876 1.1 riastrad { 877 1.1 riastrad struct drm_i915_private *dev_priv = overlay->i915; 878 1.1 riastrad int ret; 879 1.1 riastrad 880 1.1 riastrad WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); 881 1.1 riastrad 882 1.1 riastrad ret = intel_overlay_recover_from_interrupt(overlay); 883 1.1 riastrad if (ret != 0) 884 1.1 riastrad return ret; 885 1.1 riastrad 886 1.1 riastrad if (!overlay->active) 887 1.1 riastrad return 0; 888 1.1 riastrad 889 1.1 riastrad ret = intel_overlay_release_old_vid(overlay); 890 1.1 riastrad if (ret != 0) 891 1.1 riastrad return ret; 892 1.1 riastrad 893 1.1 riastrad iowrite32(0, &overlay->regs->OCMD); 894 1.1 riastrad 895 1.1 riastrad return intel_overlay_off(overlay); 896 1.1 riastrad } 897 1.1 riastrad 898 1.1 riastrad static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, 899 1.1 riastrad struct intel_crtc *crtc) 900 1.1 riastrad { 901 1.1 riastrad if (!crtc->active) 902 1.1 riastrad return -EINVAL; 903 1.1 riastrad 904 1.1 riastrad /* can't use the overlay with double wide pipe */ 905 1.1 riastrad if (crtc->config->double_wide) 906 1.1 riastrad return -EINVAL; 907 1.1 riastrad 908 1.1 riastrad return 0; 909 1.1 riastrad } 910 1.1 riastrad 911 1.1 riastrad static void update_pfit_vscale_ratio(struct intel_overlay *overlay) 912 1.1 riastrad { 913 1.1 riastrad struct drm_i915_private *dev_priv = overlay->i915; 914 1.1 riastrad u32 pfit_control = I915_READ(PFIT_CONTROL); 915 1.1 riastrad u32 ratio; 916 1.1 riastrad 917 1.1 riastrad /* XXX: This is not the same logic as in the xorg driver, but more in 918 1.1 riastrad * line with the intel documentation for the i965 919 1.1 riastrad */ 920 1.1 riastrad if (INTEL_GEN(dev_priv) >= 4) { 921 1.1 riastrad /* on i965 use the PGM reg to read out the autoscaler values */ 922 1.1 riastrad ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965; 923 1.1 riastrad } else { 924 1.1 riastrad if (pfit_control & VERT_AUTO_SCALE) 925 1.1 riastrad ratio = I915_READ(PFIT_AUTO_RATIOS); 926 1.1 riastrad else 927 1.1 riastrad ratio = I915_READ(PFIT_PGM_RATIOS); 928 1.1 riastrad ratio >>= PFIT_VERT_SCALE_SHIFT; 929 1.1 riastrad } 930 1.1 riastrad 931 1.1 riastrad overlay->pfit_vscale_ratio = ratio; 932 1.1 riastrad } 933 1.1 riastrad 934 1.1 riastrad static int check_overlay_dst(struct intel_overlay *overlay, 935 1.1 riastrad struct drm_intel_overlay_put_image *rec) 936 1.1 riastrad { 937 1.1 riastrad const struct intel_crtc_state *pipe_config = 938 1.1 riastrad overlay->crtc->config; 939 1.1 riastrad 940 1.1 riastrad if (rec->dst_x < pipe_config->pipe_src_w && 941 1.1 riastrad rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w && 942 1.1 riastrad rec->dst_y < pipe_config->pipe_src_h && 943 1.1 riastrad rec->dst_y + rec->dst_height <= pipe_config->pipe_src_h) 944 1.1 riastrad return 0; 945 1.1 riastrad else 946 1.1 riastrad return -EINVAL; 947 1.1 riastrad } 948 1.1 riastrad 949 1.1 riastrad static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec) 950 1.1 riastrad { 951 1.1 riastrad u32 tmp; 952 1.1 riastrad 953 1.1 riastrad /* downscaling limit is 8.0 */ 954 1.1 riastrad tmp = ((rec->src_scan_height << 16) / rec->dst_height) >> 16; 955 1.1 riastrad if (tmp > 7) 956 1.1 riastrad return -EINVAL; 957 1.1 riastrad 958 1.1 riastrad tmp = ((rec->src_scan_width << 16) / rec->dst_width) >> 16; 959 1.1 riastrad if (tmp > 7) 960 1.1 riastrad return -EINVAL; 961 1.1 riastrad 962 1.1 riastrad return 0; 963 1.1 riastrad } 964 1.1 riastrad 965 1.1 riastrad static int check_overlay_src(struct drm_i915_private *dev_priv, 966 1.1 riastrad struct drm_intel_overlay_put_image *rec, 967 1.1 riastrad struct drm_i915_gem_object *new_bo) 968 1.1 riastrad { 969 1.1 riastrad int uv_hscale = uv_hsubsampling(rec->flags); 970 1.1 riastrad int uv_vscale = uv_vsubsampling(rec->flags); 971 1.1 riastrad u32 stride_mask; 972 1.1 riastrad int depth; 973 1.1 riastrad u32 tmp; 974 1.1 riastrad 975 1.1 riastrad /* check src dimensions */ 976 1.1 riastrad if (IS_I845G(dev_priv) || IS_I830(dev_priv)) { 977 1.1 riastrad if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY || 978 1.1 riastrad rec->src_width > IMAGE_MAX_WIDTH_LEGACY) 979 1.1 riastrad return -EINVAL; 980 1.1 riastrad } else { 981 1.1 riastrad if (rec->src_height > IMAGE_MAX_HEIGHT || 982 1.1 riastrad rec->src_width > IMAGE_MAX_WIDTH) 983 1.1 riastrad return -EINVAL; 984 1.1 riastrad } 985 1.1 riastrad 986 1.1 riastrad /* better safe than sorry, use 4 as the maximal subsampling ratio */ 987 1.1 riastrad if (rec->src_height < N_VERT_Y_TAPS*4 || 988 1.1 riastrad rec->src_width < N_HORIZ_Y_TAPS*4) 989 1.1 riastrad return -EINVAL; 990 1.1 riastrad 991 1.1 riastrad /* check alignment constraints */ 992 1.1 riastrad switch (rec->flags & I915_OVERLAY_TYPE_MASK) { 993 1.1 riastrad case I915_OVERLAY_RGB: 994 1.1 riastrad /* not implemented */ 995 1.1 riastrad return -EINVAL; 996 1.1 riastrad 997 1.1 riastrad case I915_OVERLAY_YUV_PACKED: 998 1.1 riastrad if (uv_vscale != 1) 999 1.1 riastrad return -EINVAL; 1000 1.1 riastrad 1001 1.1 riastrad depth = packed_depth_bytes(rec->flags); 1002 1.1 riastrad if (depth < 0) 1003 1.1 riastrad return depth; 1004 1.1 riastrad 1005 1.1 riastrad /* ignore UV planes */ 1006 1.1 riastrad rec->stride_UV = 0; 1007 1.1 riastrad rec->offset_U = 0; 1008 1.1 riastrad rec->offset_V = 0; 1009 1.1 riastrad /* check pixel alignment */ 1010 1.1 riastrad if (rec->offset_Y % depth) 1011 1.1 riastrad return -EINVAL; 1012 1.1 riastrad break; 1013 1.1 riastrad 1014 1.1 riastrad case I915_OVERLAY_YUV_PLANAR: 1015 1.1 riastrad if (uv_vscale < 0 || uv_hscale < 0) 1016 1.1 riastrad return -EINVAL; 1017 1.1 riastrad /* no offset restrictions for planar formats */ 1018 1.1 riastrad break; 1019 1.1 riastrad 1020 1.1 riastrad default: 1021 1.1 riastrad return -EINVAL; 1022 1.1 riastrad } 1023 1.1 riastrad 1024 1.1 riastrad if (rec->src_width % uv_hscale) 1025 1.1 riastrad return -EINVAL; 1026 1.1 riastrad 1027 1.1 riastrad /* stride checking */ 1028 1.1 riastrad if (IS_I830(dev_priv) || IS_I845G(dev_priv)) 1029 1.1 riastrad stride_mask = 255; 1030 1.1 riastrad else 1031 1.1 riastrad stride_mask = 63; 1032 1.1 riastrad 1033 1.1 riastrad if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) 1034 1.1 riastrad return -EINVAL; 1035 1.1 riastrad if (IS_GEN(dev_priv, 4) && rec->stride_Y < 512) 1036 1.1 riastrad return -EINVAL; 1037 1.1 riastrad 1038 1.1 riastrad tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? 1039 1.1 riastrad 4096 : 8192; 1040 1.1 riastrad if (rec->stride_Y > tmp || rec->stride_UV > 2*1024) 1041 1.1 riastrad return -EINVAL; 1042 1.1 riastrad 1043 1.1 riastrad /* check buffer dimensions */ 1044 1.1 riastrad switch (rec->flags & I915_OVERLAY_TYPE_MASK) { 1045 1.1 riastrad case I915_OVERLAY_RGB: 1046 1.1 riastrad case I915_OVERLAY_YUV_PACKED: 1047 1.1 riastrad /* always 4 Y values per depth pixels */ 1048 1.1 riastrad if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y) 1049 1.1 riastrad return -EINVAL; 1050 1.1 riastrad 1051 1.1 riastrad tmp = rec->stride_Y*rec->src_height; 1052 1.1 riastrad if (rec->offset_Y + tmp > new_bo->base.size) 1053 1.1 riastrad return -EINVAL; 1054 1.1 riastrad break; 1055 1.1 riastrad 1056 1.1 riastrad case I915_OVERLAY_YUV_PLANAR: 1057 1.1 riastrad if (rec->src_width > rec->stride_Y) 1058 1.1 riastrad return -EINVAL; 1059 1.1 riastrad if (rec->src_width/uv_hscale > rec->stride_UV) 1060 1.1 riastrad return -EINVAL; 1061 1.1 riastrad 1062 1.1 riastrad tmp = rec->stride_Y * rec->src_height; 1063 1.1 riastrad if (rec->offset_Y + tmp > new_bo->base.size) 1064 1.1 riastrad return -EINVAL; 1065 1.1 riastrad 1066 1.1 riastrad tmp = rec->stride_UV * (rec->src_height / uv_vscale); 1067 1.1 riastrad if (rec->offset_U + tmp > new_bo->base.size || 1068 1.1 riastrad rec->offset_V + tmp > new_bo->base.size) 1069 1.1 riastrad return -EINVAL; 1070 1.1 riastrad break; 1071 1.1 riastrad } 1072 1.1 riastrad 1073 1.1 riastrad return 0; 1074 1.1 riastrad } 1075 1.1 riastrad 1076 1.1 riastrad int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, 1077 1.1 riastrad struct drm_file *file_priv) 1078 1.1 riastrad { 1079 1.1 riastrad struct drm_intel_overlay_put_image *params = data; 1080 1.1 riastrad struct drm_i915_private *dev_priv = to_i915(dev); 1081 1.1 riastrad struct intel_overlay *overlay; 1082 1.1 riastrad struct drm_crtc *drmmode_crtc; 1083 1.1 riastrad struct intel_crtc *crtc; 1084 1.1 riastrad struct drm_i915_gem_object *new_bo; 1085 1.1 riastrad int ret; 1086 1.1 riastrad 1087 1.1 riastrad overlay = dev_priv->overlay; 1088 1.1 riastrad if (!overlay) { 1089 1.1 riastrad DRM_DEBUG("userspace bug: no overlay\n"); 1090 1.1 riastrad return -ENODEV; 1091 1.1 riastrad } 1092 1.1 riastrad 1093 1.1 riastrad if (!(params->flags & I915_OVERLAY_ENABLE)) { 1094 1.1 riastrad drm_modeset_lock_all(dev); 1095 1.1 riastrad ret = intel_overlay_switch_off(overlay); 1096 1.1 riastrad drm_modeset_unlock_all(dev); 1097 1.1 riastrad 1098 1.1 riastrad return ret; 1099 1.1 riastrad } 1100 1.1 riastrad 1101 1.1 riastrad drmmode_crtc = drm_crtc_find(dev, file_priv, params->crtc_id); 1102 1.1 riastrad if (!drmmode_crtc) 1103 1.1 riastrad return -ENOENT; 1104 1.1 riastrad crtc = to_intel_crtc(drmmode_crtc); 1105 1.1 riastrad 1106 1.1 riastrad new_bo = i915_gem_object_lookup(file_priv, params->bo_handle); 1107 1.1 riastrad if (!new_bo) 1108 1.1 riastrad return -ENOENT; 1109 1.1 riastrad 1110 1.1 riastrad drm_modeset_lock_all(dev); 1111 1.1 riastrad 1112 1.1 riastrad if (i915_gem_object_is_tiled(new_bo)) { 1113 1.1 riastrad DRM_DEBUG_KMS("buffer used for overlay image can not be tiled\n"); 1114 1.1 riastrad ret = -EINVAL; 1115 1.1 riastrad goto out_unlock; 1116 1.1 riastrad } 1117 1.1 riastrad 1118 1.1 riastrad ret = intel_overlay_recover_from_interrupt(overlay); 1119 1.1 riastrad if (ret != 0) 1120 1.1 riastrad goto out_unlock; 1121 1.1 riastrad 1122 1.1 riastrad if (overlay->crtc != crtc) { 1123 1.1 riastrad ret = intel_overlay_switch_off(overlay); 1124 1.1 riastrad if (ret != 0) 1125 1.1 riastrad goto out_unlock; 1126 1.1 riastrad 1127 1.1 riastrad ret = check_overlay_possible_on_crtc(overlay, crtc); 1128 1.1 riastrad if (ret != 0) 1129 1.1 riastrad goto out_unlock; 1130 1.1 riastrad 1131 1.1 riastrad overlay->crtc = crtc; 1132 1.1 riastrad crtc->overlay = overlay; 1133 1.1 riastrad 1134 1.1 riastrad /* line too wide, i.e. one-line-mode */ 1135 1.1 riastrad if (crtc->config->pipe_src_w > 1024 && 1136 1.1 riastrad crtc->config->gmch_pfit.control & PFIT_ENABLE) { 1137 1.1 riastrad overlay->pfit_active = true; 1138 1.1 riastrad update_pfit_vscale_ratio(overlay); 1139 1.1 riastrad } else 1140 1.1 riastrad overlay->pfit_active = false; 1141 1.1 riastrad } 1142 1.1 riastrad 1143 1.1 riastrad ret = check_overlay_dst(overlay, params); 1144 1.1 riastrad if (ret != 0) 1145 1.1 riastrad goto out_unlock; 1146 1.1 riastrad 1147 1.1 riastrad if (overlay->pfit_active) { 1148 1.1 riastrad params->dst_y = (((u32)params->dst_y << 12) / 1149 1.1 riastrad overlay->pfit_vscale_ratio); 1150 1.1 riastrad /* shifting right rounds downwards, so add 1 */ 1151 1.1 riastrad params->dst_height = (((u32)params->dst_height << 12) / 1152 1.1 riastrad overlay->pfit_vscale_ratio) + 1; 1153 1.1 riastrad } 1154 1.1 riastrad 1155 1.1 riastrad if (params->src_scan_height > params->src_height || 1156 1.1 riastrad params->src_scan_width > params->src_width) { 1157 1.1 riastrad ret = -EINVAL; 1158 1.1 riastrad goto out_unlock; 1159 1.1 riastrad } 1160 1.1 riastrad 1161 1.1 riastrad ret = check_overlay_src(dev_priv, params, new_bo); 1162 1.1 riastrad if (ret != 0) 1163 1.1 riastrad goto out_unlock; 1164 1.1 riastrad 1165 1.1 riastrad /* Check scaling after src size to prevent a divide-by-zero. */ 1166 1.1 riastrad ret = check_overlay_scaling(params); 1167 1.1 riastrad if (ret != 0) 1168 1.1 riastrad goto out_unlock; 1169 1.1 riastrad 1170 1.1 riastrad ret = intel_overlay_do_put_image(overlay, new_bo, params); 1171 1.1 riastrad if (ret != 0) 1172 1.1 riastrad goto out_unlock; 1173 1.1 riastrad 1174 1.1 riastrad drm_modeset_unlock_all(dev); 1175 1.1 riastrad i915_gem_object_put(new_bo); 1176 1.1 riastrad 1177 1.1 riastrad return 0; 1178 1.1 riastrad 1179 1.1 riastrad out_unlock: 1180 1.1 riastrad drm_modeset_unlock_all(dev); 1181 1.1 riastrad i915_gem_object_put(new_bo); 1182 1.1 riastrad 1183 1.1 riastrad return ret; 1184 1.1 riastrad } 1185 1.1 riastrad 1186 1.1 riastrad static void update_reg_attrs(struct intel_overlay *overlay, 1187 1.1 riastrad struct overlay_registers __iomem *regs) 1188 1.1 riastrad { 1189 1.1 riastrad iowrite32((overlay->contrast << 18) | (overlay->brightness & 0xff), 1190 1.1 riastrad ®s->OCLRC0); 1191 1.1 riastrad iowrite32(overlay->saturation, ®s->OCLRC1); 1192 1.1 riastrad } 1193 1.1 riastrad 1194 1.1 riastrad static bool check_gamma_bounds(u32 gamma1, u32 gamma2) 1195 1.1 riastrad { 1196 1.1 riastrad int i; 1197 1.1 riastrad 1198 1.1 riastrad if (gamma1 & 0xff000000 || gamma2 & 0xff000000) 1199 1.1 riastrad return false; 1200 1.1 riastrad 1201 1.1 riastrad for (i = 0; i < 3; i++) { 1202 1.1 riastrad if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) 1203 1.1 riastrad return false; 1204 1.1 riastrad } 1205 1.1 riastrad 1206 1.1 riastrad return true; 1207 1.1 riastrad } 1208 1.1 riastrad 1209 1.1 riastrad static bool check_gamma5_errata(u32 gamma5) 1210 1.1 riastrad { 1211 1.1 riastrad int i; 1212 1.1 riastrad 1213 1.1 riastrad for (i = 0; i < 3; i++) { 1214 1.1 riastrad if (((gamma5 >> i*8) & 0xff) == 0x80) 1215 1.1 riastrad return false; 1216 1.1 riastrad } 1217 1.1 riastrad 1218 1.1 riastrad return true; 1219 1.1 riastrad } 1220 1.1 riastrad 1221 1.1 riastrad static int check_gamma(struct drm_intel_overlay_attrs *attrs) 1222 1.1 riastrad { 1223 1.1 riastrad if (!check_gamma_bounds(0, attrs->gamma0) || 1224 1.1 riastrad !check_gamma_bounds(attrs->gamma0, attrs->gamma1) || 1225 1.1 riastrad !check_gamma_bounds(attrs->gamma1, attrs->gamma2) || 1226 1.1 riastrad !check_gamma_bounds(attrs->gamma2, attrs->gamma3) || 1227 1.1 riastrad !check_gamma_bounds(attrs->gamma3, attrs->gamma4) || 1228 1.1 riastrad !check_gamma_bounds(attrs->gamma4, attrs->gamma5) || 1229 1.1 riastrad !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) 1230 1.1 riastrad return -EINVAL; 1231 1.1 riastrad 1232 1.1 riastrad if (!check_gamma5_errata(attrs->gamma5)) 1233 1.1 riastrad return -EINVAL; 1234 1.1 riastrad 1235 1.1 riastrad return 0; 1236 1.1 riastrad } 1237 1.1 riastrad 1238 1.1 riastrad int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, 1239 1.1 riastrad struct drm_file *file_priv) 1240 1.1 riastrad { 1241 1.1 riastrad struct drm_intel_overlay_attrs *attrs = data; 1242 1.1 riastrad struct drm_i915_private *dev_priv = to_i915(dev); 1243 1.1 riastrad struct intel_overlay *overlay; 1244 1.1 riastrad int ret; 1245 1.1 riastrad 1246 1.1 riastrad overlay = dev_priv->overlay; 1247 1.1 riastrad if (!overlay) { 1248 1.1 riastrad DRM_DEBUG("userspace bug: no overlay\n"); 1249 1.1 riastrad return -ENODEV; 1250 1.1 riastrad } 1251 1.1 riastrad 1252 1.1 riastrad drm_modeset_lock_all(dev); 1253 1.1 riastrad 1254 1.1 riastrad ret = -EINVAL; 1255 1.1 riastrad if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { 1256 1.1 riastrad attrs->color_key = overlay->color_key; 1257 1.1 riastrad attrs->brightness = overlay->brightness; 1258 1.1 riastrad attrs->contrast = overlay->contrast; 1259 1.1 riastrad attrs->saturation = overlay->saturation; 1260 1.1 riastrad 1261 1.1 riastrad if (!IS_GEN(dev_priv, 2)) { 1262 1.1 riastrad attrs->gamma0 = I915_READ(OGAMC0); 1263 1.1 riastrad attrs->gamma1 = I915_READ(OGAMC1); 1264 1.1 riastrad attrs->gamma2 = I915_READ(OGAMC2); 1265 1.1 riastrad attrs->gamma3 = I915_READ(OGAMC3); 1266 1.1 riastrad attrs->gamma4 = I915_READ(OGAMC4); 1267 1.1 riastrad attrs->gamma5 = I915_READ(OGAMC5); 1268 1.1 riastrad } 1269 1.1 riastrad } else { 1270 1.1 riastrad if (attrs->brightness < -128 || attrs->brightness > 127) 1271 1.1 riastrad goto out_unlock; 1272 1.1 riastrad if (attrs->contrast > 255) 1273 1.1 riastrad goto out_unlock; 1274 1.1 riastrad if (attrs->saturation > 1023) 1275 1.1 riastrad goto out_unlock; 1276 1.1 riastrad 1277 1.1 riastrad overlay->color_key = attrs->color_key; 1278 1.1 riastrad overlay->brightness = attrs->brightness; 1279 1.1 riastrad overlay->contrast = attrs->contrast; 1280 1.1 riastrad overlay->saturation = attrs->saturation; 1281 1.1 riastrad 1282 1.1 riastrad update_reg_attrs(overlay, overlay->regs); 1283 1.1 riastrad 1284 1.1 riastrad if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { 1285 1.1 riastrad if (IS_GEN(dev_priv, 2)) 1286 1.1 riastrad goto out_unlock; 1287 1.1 riastrad 1288 1.1 riastrad if (overlay->active) { 1289 1.1 riastrad ret = -EBUSY; 1290 1.1 riastrad goto out_unlock; 1291 1.1 riastrad } 1292 1.1 riastrad 1293 1.1 riastrad ret = check_gamma(attrs); 1294 1.1 riastrad if (ret) 1295 1.1 riastrad goto out_unlock; 1296 1.1 riastrad 1297 1.1 riastrad I915_WRITE(OGAMC0, attrs->gamma0); 1298 1.1 riastrad I915_WRITE(OGAMC1, attrs->gamma1); 1299 1.1 riastrad I915_WRITE(OGAMC2, attrs->gamma2); 1300 1.1 riastrad I915_WRITE(OGAMC3, attrs->gamma3); 1301 1.1 riastrad I915_WRITE(OGAMC4, attrs->gamma4); 1302 1.1 riastrad I915_WRITE(OGAMC5, attrs->gamma5); 1303 1.1 riastrad } 1304 1.1 riastrad } 1305 1.1 riastrad overlay->color_key_enabled = (attrs->flags & I915_OVERLAY_DISABLE_DEST_COLORKEY) == 0; 1306 1.1 riastrad 1307 1.1 riastrad ret = 0; 1308 1.1 riastrad out_unlock: 1309 1.1 riastrad drm_modeset_unlock_all(dev); 1310 1.1 riastrad 1311 1.1 riastrad return ret; 1312 1.1 riastrad } 1313 1.1 riastrad 1314 1.1 riastrad static int get_registers(struct intel_overlay *overlay, bool use_phys) 1315 1.1 riastrad { 1316 1.1 riastrad struct drm_i915_private *i915 = overlay->i915; 1317 1.1 riastrad struct drm_i915_gem_object *obj; 1318 1.1 riastrad struct i915_vma *vma; 1319 1.1 riastrad int err; 1320 1.1 riastrad 1321 1.1 riastrad obj = i915_gem_object_create_stolen(i915, PAGE_SIZE); 1322 1.1 riastrad if (IS_ERR(obj)) 1323 1.1 riastrad obj = i915_gem_object_create_internal(i915, PAGE_SIZE); 1324 1.1 riastrad if (IS_ERR(obj)) 1325 1.1 riastrad return PTR_ERR(obj); 1326 1.1 riastrad 1327 1.1 riastrad vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE); 1328 1.1 riastrad if (IS_ERR(vma)) { 1329 1.1 riastrad err = PTR_ERR(vma); 1330 1.1 riastrad goto err_put_bo; 1331 1.1 riastrad } 1332 1.1 riastrad 1333 1.1 riastrad if (use_phys) 1334 1.1 riastrad overlay->flip_addr = sg_dma_address(obj->mm.pages->sgl); 1335 1.1 riastrad else 1336 1.1 riastrad overlay->flip_addr = i915_ggtt_offset(vma); 1337 1.1 riastrad overlay->regs = i915_vma_pin_iomap(vma); 1338 1.1 riastrad i915_vma_unpin(vma); 1339 1.1 riastrad 1340 1.1 riastrad if (IS_ERR(overlay->regs)) { 1341 1.1 riastrad err = PTR_ERR(overlay->regs); 1342 1.1 riastrad goto err_put_bo; 1343 1.1 riastrad } 1344 1.1 riastrad 1345 1.1 riastrad overlay->reg_bo = obj; 1346 1.1 riastrad return 0; 1347 1.1 riastrad 1348 1.1 riastrad err_put_bo: 1349 1.1 riastrad i915_gem_object_put(obj); 1350 1.1 riastrad return err; 1351 1.1 riastrad } 1352 1.1 riastrad 1353 1.1 riastrad void intel_overlay_setup(struct drm_i915_private *dev_priv) 1354 1.1 riastrad { 1355 1.1 riastrad struct intel_overlay *overlay; 1356 1.1 riastrad struct intel_engine_cs *engine; 1357 1.1 riastrad int ret; 1358 1.1 riastrad 1359 1.1 riastrad if (!HAS_OVERLAY(dev_priv)) 1360 1.1 riastrad return; 1361 1.1 riastrad 1362 1.1 riastrad engine = dev_priv->engine[RCS0]; 1363 1.1 riastrad if (!engine || !engine->kernel_context) 1364 1.1 riastrad return; 1365 1.1 riastrad 1366 1.1 riastrad overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); 1367 1.1 riastrad if (!overlay) 1368 1.1 riastrad return; 1369 1.1 riastrad 1370 1.1 riastrad overlay->i915 = dev_priv; 1371 1.1 riastrad overlay->context = engine->kernel_context; 1372 1.1 riastrad GEM_BUG_ON(!overlay->context); 1373 1.1 riastrad 1374 1.1 riastrad overlay->color_key = 0x0101fe; 1375 1.1 riastrad overlay->color_key_enabled = true; 1376 1.1 riastrad overlay->brightness = -19; 1377 1.1 riastrad overlay->contrast = 75; 1378 1.1 riastrad overlay->saturation = 146; 1379 1.1 riastrad 1380 1.1 riastrad i915_active_init(&overlay->last_flip, 1381 1.1 riastrad NULL, intel_overlay_last_flip_retire); 1382 1.1 riastrad 1383 1.1 riastrad ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv)); 1384 1.1 riastrad if (ret) 1385 1.1 riastrad goto out_free; 1386 1.1 riastrad 1387 1.1 riastrad memset_io(overlay->regs, 0, sizeof(struct overlay_registers)); 1388 1.1 riastrad update_polyphase_filter(overlay->regs); 1389 1.1 riastrad update_reg_attrs(overlay, overlay->regs); 1390 1.1 riastrad 1391 1.1 riastrad dev_priv->overlay = overlay; 1392 1.1 riastrad DRM_INFO("Initialized overlay support.\n"); 1393 1.1 riastrad return; 1394 1.1 riastrad 1395 1.1 riastrad out_free: 1396 1.1 riastrad kfree(overlay); 1397 1.1 riastrad } 1398 1.1 riastrad 1399 1.1 riastrad void intel_overlay_cleanup(struct drm_i915_private *dev_priv) 1400 1.1 riastrad { 1401 1.1 riastrad struct intel_overlay *overlay; 1402 1.1 riastrad 1403 1.1 riastrad overlay = fetch_and_zero(&dev_priv->overlay); 1404 1.1 riastrad if (!overlay) 1405 1.1 riastrad return; 1406 1.1 riastrad 1407 1.1 riastrad /* 1408 1.1 riastrad * The bo's should be free'd by the generic code already. 1409 1.1 riastrad * Furthermore modesetting teardown happens beforehand so the 1410 1.1 riastrad * hardware should be off already. 1411 1.1 riastrad */ 1412 1.1 riastrad WARN_ON(overlay->active); 1413 1.1 riastrad 1414 1.1 riastrad i915_gem_object_put(overlay->reg_bo); 1415 1.1 riastrad i915_active_fini(&overlay->last_flip); 1416 1.1 riastrad 1417 1.1 riastrad kfree(overlay); 1418 1.1 riastrad } 1419 1.1 riastrad 1420 1.1 riastrad #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) 1421 1.1 riastrad 1422 1.1 riastrad struct intel_overlay_error_state { 1423 1.1 riastrad struct overlay_registers regs; 1424 1.1 riastrad unsigned long base; 1425 1.1 riastrad u32 dovsta; 1426 1.1 riastrad u32 isr; 1427 1.1 riastrad }; 1428 1.1 riastrad 1429 1.1 riastrad struct intel_overlay_error_state * 1430 1.1 riastrad intel_overlay_capture_error_state(struct drm_i915_private *dev_priv) 1431 1.1 riastrad { 1432 1.1 riastrad struct intel_overlay *overlay = dev_priv->overlay; 1433 1.1 riastrad struct intel_overlay_error_state *error; 1434 1.1 riastrad 1435 1.1 riastrad if (!overlay || !overlay->active) 1436 1.1 riastrad return NULL; 1437 1.1 riastrad 1438 1.1 riastrad error = kmalloc(sizeof(*error), GFP_ATOMIC); 1439 1.1 riastrad if (error == NULL) 1440 1.1 riastrad return NULL; 1441 1.1 riastrad 1442 1.1 riastrad error->dovsta = I915_READ(DOVSTA); 1443 1.1 riastrad error->isr = I915_READ(GEN2_ISR); 1444 1.1 riastrad error->base = overlay->flip_addr; 1445 1.1 riastrad 1446 1.1 riastrad memcpy_fromio(&error->regs, overlay->regs, sizeof(error->regs)); 1447 1.1 riastrad 1448 1.1 riastrad return error; 1449 1.1 riastrad } 1450 1.1 riastrad 1451 1.1 riastrad void 1452 1.1 riastrad intel_overlay_print_error_state(struct drm_i915_error_state_buf *m, 1453 1.1 riastrad struct intel_overlay_error_state *error) 1454 1.1 riastrad { 1455 1.1 riastrad i915_error_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n", 1456 1.1 riastrad error->dovsta, error->isr); 1457 1.1 riastrad i915_error_printf(m, " Register file at 0x%08lx:\n", 1458 1.1 riastrad error->base); 1459 1.1 riastrad 1460 1.1 riastrad #define P(x) i915_error_printf(m, " " #x ": 0x%08x\n", error->regs.x) 1461 1.1 riastrad P(OBUF_0Y); 1462 1.1 riastrad P(OBUF_1Y); 1463 1.1 riastrad P(OBUF_0U); 1464 1.1 riastrad P(OBUF_0V); 1465 1.1 riastrad P(OBUF_1U); 1466 1.1 riastrad P(OBUF_1V); 1467 1.1 riastrad P(OSTRIDE); 1468 1.1 riastrad P(YRGB_VPH); 1469 1.1 riastrad P(UV_VPH); 1470 1.1 riastrad P(HORZ_PH); 1471 1.1 riastrad P(INIT_PHS); 1472 1.1 riastrad P(DWINPOS); 1473 1.1 riastrad P(DWINSZ); 1474 1.1 riastrad P(SWIDTH); 1475 1.1 riastrad P(SWIDTHSW); 1476 1.1 riastrad P(SHEIGHT); 1477 1.1 riastrad P(YRGBSCALE); 1478 1.1 riastrad P(UVSCALE); 1479 1.1 riastrad P(OCLRC0); 1480 1.1 riastrad P(OCLRC1); 1481 1.1 riastrad P(DCLRKV); 1482 1.1 riastrad P(DCLRKM); 1483 1.1 riastrad P(SCLRKVH); 1484 1.1 riastrad P(SCLRKVL); 1485 1.1 riastrad P(SCLRKEN); 1486 1.1 riastrad P(OCONFIG); 1487 1.1 riastrad P(OCMD); 1488 1.1 riastrad P(OSTART_0Y); 1489 1.1 riastrad P(OSTART_1Y); 1490 1.1 riastrad P(OSTART_0U); 1491 1.1 riastrad P(OSTART_0V); 1492 1.1 riastrad P(OSTART_1U); 1493 1.1 riastrad P(OSTART_1V); 1494 1.1 riastrad P(OTILEOFF_0Y); 1495 1.1 riastrad P(OTILEOFF_1Y); 1496 1.1 riastrad P(OTILEOFF_0U); 1497 1.1 riastrad P(OTILEOFF_0V); 1498 1.1 riastrad P(OTILEOFF_1U); 1499 1.1 riastrad P(OTILEOFF_1V); 1500 1.1 riastrad P(FASTHSCALE); 1501 1.1 riastrad P(UVSCALEV); 1502 1.1 riastrad #undef P 1503 1.1 riastrad } 1504 1.1 riastrad 1505 1.1 riastrad #endif 1506