blob: 5ed1783a69a0670a6e94527ef87b8e28974bdde6 [file] [log] [blame]
Daniel Vetter02e792f2009-09-15 22:57:34 +02001/*
2 * Copyright © 2009
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Daniel Vetter <daniel@ffwll.ch>
25 *
26 * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
27 */
Andrew Mortone1679762010-08-24 16:35:52 -070028
29#include <linux/seq_file.h>
Daniel Vetter02e792f2009-09-15 22:57:34 +020030#include "drmP.h"
31#include "drm.h"
32#include "i915_drm.h"
33#include "i915_drv.h"
34#include "i915_reg.h"
35#include "intel_drv.h"
36
37/* Limits for overlay size. According to intel doc, the real limits are:
38 * Y width: 4095, UV width (planar): 2047, Y height: 2047,
39 * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
40 * the mininum of both. */
41#define IMAGE_MAX_WIDTH 2048
42#define IMAGE_MAX_HEIGHT 2046 /* 2 * 1023 */
43/* on 830 and 845 these large limits result in the card hanging */
44#define IMAGE_MAX_WIDTH_LEGACY 1024
45#define IMAGE_MAX_HEIGHT_LEGACY 1088
46
47/* overlay register definitions */
48/* OCMD register */
49#define OCMD_TILED_SURFACE (0x1<<19)
50#define OCMD_MIRROR_MASK (0x3<<17)
51#define OCMD_MIRROR_MODE (0x3<<17)
52#define OCMD_MIRROR_HORIZONTAL (0x1<<17)
53#define OCMD_MIRROR_VERTICAL (0x2<<17)
54#define OCMD_MIRROR_BOTH (0x3<<17)
55#define OCMD_BYTEORDER_MASK (0x3<<14) /* zero for YUYV or FOURCC YUY2 */
56#define OCMD_UV_SWAP (0x1<<14) /* YVYU */
57#define OCMD_Y_SWAP (0x2<<14) /* UYVY or FOURCC UYVY */
58#define OCMD_Y_AND_UV_SWAP (0x3<<14) /* VYUY */
59#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
60#define OCMD_RGB_888 (0x1<<10) /* not in i965 Intel docs */
61#define OCMD_RGB_555 (0x2<<10) /* not in i965 Intel docs */
62#define OCMD_RGB_565 (0x3<<10) /* not in i965 Intel docs */
63#define OCMD_YUV_422_PACKED (0x8<<10)
64#define OCMD_YUV_411_PACKED (0x9<<10) /* not in i965 Intel docs */
65#define OCMD_YUV_420_PLANAR (0xc<<10)
66#define OCMD_YUV_422_PLANAR (0xd<<10)
67#define OCMD_YUV_410_PLANAR (0xe<<10) /* also 411 */
68#define OCMD_TVSYNCFLIP_PARITY (0x1<<9)
69#define OCMD_TVSYNCFLIP_ENABLE (0x1<<7)
Chris Wilsond7961362010-07-13 13:52:17 +010070#define OCMD_BUF_TYPE_MASK (0x1<<5)
Daniel Vetter02e792f2009-09-15 22:57:34 +020071#define OCMD_BUF_TYPE_FRAME (0x0<<5)
72#define OCMD_BUF_TYPE_FIELD (0x1<<5)
73#define OCMD_TEST_MODE (0x1<<4)
74#define OCMD_BUFFER_SELECT (0x3<<2)
75#define OCMD_BUFFER0 (0x0<<2)
76#define OCMD_BUFFER1 (0x1<<2)
77#define OCMD_FIELD_SELECT (0x1<<2)
78#define OCMD_FIELD0 (0x0<<1)
79#define OCMD_FIELD1 (0x1<<1)
80#define OCMD_ENABLE (0x1<<0)
81
82/* OCONFIG register */
83#define OCONF_PIPE_MASK (0x1<<18)
84#define OCONF_PIPE_A (0x0<<18)
85#define OCONF_PIPE_B (0x1<<18)
86#define OCONF_GAMMA2_ENABLE (0x1<<16)
87#define OCONF_CSC_MODE_BT601 (0x0<<5)
88#define OCONF_CSC_MODE_BT709 (0x1<<5)
89#define OCONF_CSC_BYPASS (0x1<<4)
90#define OCONF_CC_OUT_8BIT (0x1<<3)
91#define OCONF_TEST_MODE (0x1<<2)
92#define OCONF_THREE_LINE_BUFFER (0x1<<0)
93#define OCONF_TWO_LINE_BUFFER (0x0<<0)
94
95/* DCLRKM (dst-key) register */
96#define DST_KEY_ENABLE (0x1<<31)
97#define CLK_RGB24_MASK 0x0
98#define CLK_RGB16_MASK 0x070307
99#define CLK_RGB15_MASK 0x070707
100#define CLK_RGB8I_MASK 0xffffff
101
102#define RGB16_TO_COLORKEY(c) \
103 (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
104#define RGB15_TO_COLORKEY(c) \
105 (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
106
107/* overlay flip addr flag */
108#define OFC_UPDATE 0x1
109
110/* polyphase filter coefficients */
111#define N_HORIZ_Y_TAPS 5
112#define N_VERT_Y_TAPS 3
113#define N_HORIZ_UV_TAPS 3
114#define N_VERT_UV_TAPS 3
115#define N_PHASES 17
116#define MAX_TAPS 5
117
118/* memory bufferd overlay registers */
119struct overlay_registers {
120 u32 OBUF_0Y;
121 u32 OBUF_1Y;
122 u32 OBUF_0U;
123 u32 OBUF_0V;
124 u32 OBUF_1U;
125 u32 OBUF_1V;
126 u32 OSTRIDE;
127 u32 YRGB_VPH;
128 u32 UV_VPH;
129 u32 HORZ_PH;
130 u32 INIT_PHS;
131 u32 DWINPOS;
132 u32 DWINSZ;
133 u32 SWIDTH;
134 u32 SWIDTHSW;
135 u32 SHEIGHT;
136 u32 YRGBSCALE;
137 u32 UVSCALE;
138 u32 OCLRC0;
139 u32 OCLRC1;
140 u32 DCLRKV;
141 u32 DCLRKM;
142 u32 SCLRKVH;
143 u32 SCLRKVL;
144 u32 SCLRKEN;
145 u32 OCONFIG;
146 u32 OCMD;
147 u32 RESERVED1; /* 0x6C */
148 u32 OSTART_0Y;
149 u32 OSTART_1Y;
150 u32 OSTART_0U;
151 u32 OSTART_0V;
152 u32 OSTART_1U;
153 u32 OSTART_1V;
154 u32 OTILEOFF_0Y;
155 u32 OTILEOFF_1Y;
156 u32 OTILEOFF_0U;
157 u32 OTILEOFF_0V;
158 u32 OTILEOFF_1U;
159 u32 OTILEOFF_1V;
160 u32 FASTHSCALE; /* 0xA0 */
161 u32 UVSCALEV; /* 0xA4 */
162 u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
163 u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
164 u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
165 u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
166 u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
167 u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
168 u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
169 u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
170 u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
171};
172
173/* overlay flip addr flag */
174#define OFC_UPDATE 0x1
175
176#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
Eric Anholtbad720f2009-10-22 16:11:14 -0700177#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev))
Daniel Vetter02e792f2009-09-15 22:57:34 +0200178
Daniel Vetter02e792f2009-09-15 22:57:34 +0200179static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
180{
181 drm_i915_private_t *dev_priv = overlay->dev->dev_private;
182 struct overlay_registers *regs;
183
184 /* no recursive mappings */
185 BUG_ON(overlay->virt_addr);
186
187 if (OVERLAY_NONPHYSICAL(overlay->dev)) {
188 regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
Chris Wilsonfca3ec02010-08-04 14:34:24 +0100189 overlay->reg_bo->gtt_offset,
190 KM_USER0);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200191
192 if (!regs) {
193 DRM_ERROR("failed to map overlay regs in GTT\n");
194 return NULL;
195 }
196 } else
197 regs = overlay->reg_bo->phys_obj->handle->vaddr;
198
199 return overlay->virt_addr = regs;
200}
201
202static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
203{
Daniel Vetter02e792f2009-09-15 22:57:34 +0200204 if (OVERLAY_NONPHYSICAL(overlay->dev))
Chris Wilsonfca3ec02010-08-04 14:34:24 +0100205 io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200206
207 overlay->virt_addr = NULL;
208
Daniel Vetter02e792f2009-09-15 22:57:34 +0200209 return;
210}
211
212/* overlay needs to be disable in OCMD reg */
213static int intel_overlay_on(struct intel_overlay *overlay)
214{
215 struct drm_device *dev = overlay->dev;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200216 int ret;
Zou Nan hai852835f2010-05-21 09:08:56 +0800217 drm_i915_private_t *dev_priv = dev->dev_private;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200218
219 BUG_ON(overlay->active);
220
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200221 overlay->active = 1;
222 overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP;
223
Daniel Vetter4f8a5672010-02-11 14:14:43 +0100224 BEGIN_LP_RING(4);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200225 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
226 OUT_RING(overlay->flip_addr | OFC_UPDATE);
227 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
228 OUT_RING(MI_NOOP);
229 ADVANCE_LP_RING();
230
Zou Nan hai852835f2010-05-21 09:08:56 +0800231 overlay->last_flip_req =
Daniel Vetter8a1a49f2010-02-11 22:29:04 +0100232 i915_add_request(dev, NULL, &dev_priv->render_ring);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200233 if (overlay->last_flip_req == 0)
234 return -ENOMEM;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200235
Zou Nan hai852835f2010-05-21 09:08:56 +0800236 ret = i915_do_wait_request(dev,
Chris Wilson722506f2010-08-12 09:28:50 +0100237 overlay->last_flip_req, true,
238 &dev_priv->render_ring);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200239 if (ret != 0)
240 return ret;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200241
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200242 overlay->hw_wedged = 0;
243 overlay->last_flip_req = 0;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200244 return 0;
245}
246
247/* overlay needs to be enabled in OCMD reg */
248static void intel_overlay_continue(struct intel_overlay *overlay,
Chris Wilson722506f2010-08-12 09:28:50 +0100249 bool load_polyphase_filter)
Daniel Vetter02e792f2009-09-15 22:57:34 +0200250{
251 struct drm_device *dev = overlay->dev;
252 drm_i915_private_t *dev_priv = dev->dev_private;
253 u32 flip_addr = overlay->flip_addr;
254 u32 tmp;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200255
256 BUG_ON(!overlay->active);
257
258 if (load_polyphase_filter)
259 flip_addr |= OFC_UPDATE;
260
261 /* check for underruns */
262 tmp = I915_READ(DOVSTA);
263 if (tmp & (1 << 17))
264 DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
265
Daniel Vetter4f8a5672010-02-11 14:14:43 +0100266 BEGIN_LP_RING(2);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200267 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
268 OUT_RING(flip_addr);
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200269 ADVANCE_LP_RING();
270
Zou Nan hai852835f2010-05-21 09:08:56 +0800271 overlay->last_flip_req =
Daniel Vetter8a1a49f2010-02-11 22:29:04 +0100272 i915_add_request(dev, NULL, &dev_priv->render_ring);
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200273}
274
275static int intel_overlay_wait_flip(struct intel_overlay *overlay)
276{
277 struct drm_device *dev = overlay->dev;
Chris Wilson722506f2010-08-12 09:28:50 +0100278 drm_i915_private_t *dev_priv = dev->dev_private;
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200279 int ret;
280 u32 tmp;
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200281
282 if (overlay->last_flip_req != 0) {
Chris Wilson722506f2010-08-12 09:28:50 +0100283 ret = i915_do_wait_request(dev,
284 overlay->last_flip_req, true,
285 &dev_priv->render_ring);
Daniel Vetter5c5a4352009-10-04 15:00:36 +0200286 if (ret == 0) {
287 overlay->last_flip_req = 0;
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200288
Daniel Vetter5c5a4352009-10-04 15:00:36 +0200289 tmp = I915_READ(ISR);
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200290
Daniel Vetter5c5a4352009-10-04 15:00:36 +0200291 if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT))
292 return 0;
293 }
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200294 }
295
296 /* synchronous slowpath */
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200297 overlay->hw_wedged = RELEASE_OLD_VID;
298
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200299 BEGIN_LP_RING(2);
Chris Wilson722506f2010-08-12 09:28:50 +0100300 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
301 OUT_RING(MI_NOOP);
302 ADVANCE_LP_RING();
Daniel Vetter02e792f2009-09-15 22:57:34 +0200303
Zou Nan hai852835f2010-05-21 09:08:56 +0800304 overlay->last_flip_req =
Daniel Vetter8a1a49f2010-02-11 22:29:04 +0100305 i915_add_request(dev, NULL, &dev_priv->render_ring);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200306 if (overlay->last_flip_req == 0)
307 return -ENOMEM;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200308
Chris Wilson722506f2010-08-12 09:28:50 +0100309 ret = i915_do_wait_request(dev,
310 overlay->last_flip_req, true,
311 &dev_priv->render_ring);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200312 if (ret != 0)
313 return ret;
314
315 overlay->hw_wedged = 0;
316 overlay->last_flip_req = 0;
317 return 0;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200318}
319
320/* overlay needs to be disabled in OCMD reg */
321static int intel_overlay_off(struct intel_overlay *overlay)
322{
323 u32 flip_addr = overlay->flip_addr;
324 struct drm_device *dev = overlay->dev;
Zou Nan hai852835f2010-05-21 09:08:56 +0800325 drm_i915_private_t *dev_priv = dev->dev_private;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200326 int ret;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200327
328 BUG_ON(!overlay->active);
329
330 /* According to intel docs the overlay hw may hang (when switching
331 * off) without loading the filter coeffs. It is however unclear whether
332 * this applies to the disabling of the overlay or to the switching off
333 * of the hw. Do it in both cases */
334 flip_addr |= OFC_UPDATE;
335
336 /* wait for overlay to go idle */
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200337 overlay->hw_wedged = SWITCH_OFF_STAGE_1;
338
Daniel Vetter4f8a5672010-02-11 14:14:43 +0100339 BEGIN_LP_RING(4);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200340 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
341 OUT_RING(flip_addr);
Chris Wilson722506f2010-08-12 09:28:50 +0100342 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
343 OUT_RING(MI_NOOP);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200344 ADVANCE_LP_RING();
345
Zou Nan hai852835f2010-05-21 09:08:56 +0800346 overlay->last_flip_req =
Daniel Vetter8a1a49f2010-02-11 22:29:04 +0100347 i915_add_request(dev, NULL, &dev_priv->render_ring);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200348 if (overlay->last_flip_req == 0)
349 return -ENOMEM;
350
Chris Wilson722506f2010-08-12 09:28:50 +0100351 ret = i915_do_wait_request(dev,
352 overlay->last_flip_req, true,
353 &dev_priv->render_ring);
354 if (ret != 0)
355 return ret;
356
357 /* turn overlay off */
358 overlay->hw_wedged = SWITCH_OFF_STAGE_2;
359
360 BEGIN_LP_RING(4);
361 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
362 OUT_RING(flip_addr);
363 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
364 OUT_RING(MI_NOOP);
365 ADVANCE_LP_RING();
366
367 overlay->last_flip_req =
368 i915_add_request(dev, NULL, &dev_priv->render_ring);
369 if (overlay->last_flip_req == 0)
370 return -ENOMEM;
371
372 ret = i915_do_wait_request(dev,
373 overlay->last_flip_req, true,
374 &dev_priv->render_ring);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200375 if (ret != 0)
Daniel Vetter02e792f2009-09-15 22:57:34 +0200376 return ret;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200377
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200378 overlay->hw_wedged = 0;
379 overlay->last_flip_req = 0;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200380 return ret;
381}
382
Daniel Vetter12ca45f2037-04-25 10:08:26 +0200383static void intel_overlay_off_tail(struct intel_overlay *overlay)
384{
385 struct drm_gem_object *obj;
386
387 /* never have the overlay hw on without showing a frame */
388 BUG_ON(!overlay->vid_bo);
Daniel Vettera8089e82010-04-09 19:05:09 +0000389 obj = &overlay->vid_bo->base;
Daniel Vetter12ca45f2037-04-25 10:08:26 +0200390
391 i915_gem_object_unpin(obj);
392 drm_gem_object_unreference(obj);
393 overlay->vid_bo = NULL;
394
395 overlay->crtc->overlay = NULL;
396 overlay->crtc = NULL;
397 overlay->active = 0;
398}
399
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200400/* recover from an interruption due to a signal
401 * We have to be careful not to repeat work forever an make forward progess. */
402int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
Chris Wilson722506f2010-08-12 09:28:50 +0100403 bool interruptible)
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200404{
405 struct drm_device *dev = overlay->dev;
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200406 struct drm_gem_object *obj;
Zou Nan hai852835f2010-05-21 09:08:56 +0800407 drm_i915_private_t *dev_priv = dev->dev_private;
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200408 u32 flip_addr;
409 int ret;
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200410
411 if (overlay->hw_wedged == HW_WEDGED)
412 return -EIO;
413
414 if (overlay->last_flip_req == 0) {
Zou Nan hai852835f2010-05-21 09:08:56 +0800415 overlay->last_flip_req =
Daniel Vetter8a1a49f2010-02-11 22:29:04 +0100416 i915_add_request(dev, NULL, &dev_priv->render_ring);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200417 if (overlay->last_flip_req == 0)
418 return -ENOMEM;
419 }
420
Zou Nan hai852835f2010-05-21 09:08:56 +0800421 ret = i915_do_wait_request(dev, overlay->last_flip_req,
Chris Wilson722506f2010-08-12 09:28:50 +0100422 interruptible, &dev_priv->render_ring);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200423 if (ret != 0)
424 return ret;
425
426 switch (overlay->hw_wedged) {
Chris Wilson722506f2010-08-12 09:28:50 +0100427 case RELEASE_OLD_VID:
428 obj = &overlay->old_vid_bo->base;
429 i915_gem_object_unpin(obj);
430 drm_gem_object_unreference(obj);
431 overlay->old_vid_bo = NULL;
432 break;
433 case SWITCH_OFF_STAGE_1:
434 flip_addr = overlay->flip_addr;
435 flip_addr |= OFC_UPDATE;
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200436
Chris Wilson722506f2010-08-12 09:28:50 +0100437 overlay->hw_wedged = SWITCH_OFF_STAGE_2;
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200438
Chris Wilson722506f2010-08-12 09:28:50 +0100439 BEGIN_LP_RING(4);
440 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
441 OUT_RING(flip_addr);
442 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
443 OUT_RING(MI_NOOP);
444 ADVANCE_LP_RING();
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200445
Chris Wilson722506f2010-08-12 09:28:50 +0100446 overlay->last_flip_req =
447 i915_add_request(dev, NULL,
448 &dev_priv->render_ring);
449 if (overlay->last_flip_req == 0)
450 return -ENOMEM;
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200451
Chris Wilson722506f2010-08-12 09:28:50 +0100452 ret = i915_do_wait_request(dev, overlay->last_flip_req,
453 interruptible,
454 &dev_priv->render_ring);
455 if (ret != 0)
456 return ret;
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200457
Chris Wilson722506f2010-08-12 09:28:50 +0100458 case SWITCH_OFF_STAGE_2:
459 intel_overlay_off_tail(overlay);
460 break;
461 default:
462 BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200463 }
464
465 overlay->hw_wedged = 0;
466 overlay->last_flip_req = 0;
467 return 0;
468}
469
Daniel Vetter5a5a0c62009-09-15 22:57:36 +0200470/* Wait for pending overlay flip and release old frame.
471 * Needs to be called before the overlay register are changed
472 * via intel_overlay_(un)map_regs_atomic */
Daniel Vetter02e792f2009-09-15 22:57:34 +0200473static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
474{
475 int ret;
476 struct drm_gem_object *obj;
477
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200478 /* only wait if there is actually an old frame to release to
479 * guarantee forward progress */
480 if (!overlay->old_vid_bo)
481 return 0;
482
Daniel Vetter02e792f2009-09-15 22:57:34 +0200483 ret = intel_overlay_wait_flip(overlay);
484 if (ret != 0)
485 return ret;
486
Daniel Vettera8089e82010-04-09 19:05:09 +0000487 obj = &overlay->old_vid_bo->base;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200488 i915_gem_object_unpin(obj);
489 drm_gem_object_unreference(obj);
490 overlay->old_vid_bo = NULL;
491
492 return 0;
493}
494
495struct put_image_params {
496 int format;
497 short dst_x;
498 short dst_y;
499 short dst_w;
500 short dst_h;
501 short src_w;
502 short src_scan_h;
503 short src_scan_w;
504 short src_h;
505 short stride_Y;
506 short stride_UV;
507 int offset_Y;
508 int offset_U;
509 int offset_V;
510};
511
512static int packed_depth_bytes(u32 format)
513{
514 switch (format & I915_OVERLAY_DEPTH_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +0100515 case I915_OVERLAY_YUV422:
516 return 4;
517 case I915_OVERLAY_YUV411:
518 /* return 6; not implemented */
519 default:
520 return -EINVAL;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200521 }
522}
523
524static int packed_width_bytes(u32 format, short width)
525{
526 switch (format & I915_OVERLAY_DEPTH_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +0100527 case I915_OVERLAY_YUV422:
528 return width << 1;
529 default:
530 return -EINVAL;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200531 }
532}
533
534static int uv_hsubsampling(u32 format)
535{
536 switch (format & I915_OVERLAY_DEPTH_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +0100537 case I915_OVERLAY_YUV422:
538 case I915_OVERLAY_YUV420:
539 return 2;
540 case I915_OVERLAY_YUV411:
541 case I915_OVERLAY_YUV410:
542 return 4;
543 default:
544 return -EINVAL;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200545 }
546}
547
548static int uv_vsubsampling(u32 format)
549{
550 switch (format & I915_OVERLAY_DEPTH_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +0100551 case I915_OVERLAY_YUV420:
552 case I915_OVERLAY_YUV410:
553 return 2;
554 case I915_OVERLAY_YUV422:
555 case I915_OVERLAY_YUV411:
556 return 1;
557 default:
558 return -EINVAL;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200559 }
560}
561
562static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
563{
564 u32 mask, shift, ret;
565 if (IS_I9XX(dev)) {
566 mask = 0x3f;
567 shift = 6;
568 } else {
569 mask = 0x1f;
570 shift = 5;
571 }
572 ret = ((offset + width + mask) >> shift) - (offset >> shift);
573 if (IS_I9XX(dev))
574 ret <<= 1;
575 ret -=1;
576 return ret << 2;
577}
578
579static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
580 0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
581 0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
582 0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
583 0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
584 0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
585 0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
586 0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
587 0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
588 0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
589 0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
590 0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
591 0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
592 0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
593 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
594 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
595 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
Chris Wilson722506f2010-08-12 09:28:50 +0100596 0xb000, 0x3000, 0x0800, 0x3000, 0xb000
597};
598
Daniel Vetter02e792f2009-09-15 22:57:34 +0200599static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
600 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
601 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
602 0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
603 0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
604 0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
605 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
606 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
607 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
Chris Wilson722506f2010-08-12 09:28:50 +0100608 0x3000, 0x0800, 0x3000
609};
Daniel Vetter02e792f2009-09-15 22:57:34 +0200610
611static void update_polyphase_filter(struct overlay_registers *regs)
612{
613 memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
614 memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
615}
616
617static bool update_scaling_factors(struct intel_overlay *overlay,
618 struct overlay_registers *regs,
619 struct put_image_params *params)
620{
621 /* fixed point with a 12 bit shift */
622 u32 xscale, yscale, xscale_UV, yscale_UV;
623#define FP_SHIFT 12
624#define FRACT_MASK 0xfff
625 bool scale_changed = false;
626 int uv_hscale = uv_hsubsampling(params->format);
627 int uv_vscale = uv_vsubsampling(params->format);
628
629 if (params->dst_w > 1)
630 xscale = ((params->src_scan_w - 1) << FP_SHIFT)
631 /(params->dst_w);
632 else
633 xscale = 1 << FP_SHIFT;
634
635 if (params->dst_h > 1)
636 yscale = ((params->src_scan_h - 1) << FP_SHIFT)
637 /(params->dst_h);
638 else
639 yscale = 1 << FP_SHIFT;
640
641 /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
Chris Wilson722506f2010-08-12 09:28:50 +0100642 xscale_UV = xscale/uv_hscale;
643 yscale_UV = yscale/uv_vscale;
644 /* make the Y scale to UV scale ratio an exact multiply */
645 xscale = xscale_UV * uv_hscale;
646 yscale = yscale_UV * uv_vscale;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200647 /*} else {
Chris Wilson722506f2010-08-12 09:28:50 +0100648 xscale_UV = 0;
649 yscale_UV = 0;
650 }*/
Daniel Vetter02e792f2009-09-15 22:57:34 +0200651
652 if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
653 scale_changed = true;
654 overlay->old_xscale = xscale;
655 overlay->old_yscale = yscale;
656
Chris Wilson722506f2010-08-12 09:28:50 +0100657 regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
658 ((xscale >> FP_SHIFT) << 16) |
659 ((xscale & FRACT_MASK) << 3));
660
661 regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
662 ((xscale_UV >> FP_SHIFT) << 16) |
663 ((xscale_UV & FRACT_MASK) << 3));
664
665 regs->UVSCALEV = ((((yscale >> FP_SHIFT) << 16) |
666 ((yscale_UV >> FP_SHIFT) << 0)));
Daniel Vetter02e792f2009-09-15 22:57:34 +0200667
668 if (scale_changed)
669 update_polyphase_filter(regs);
670
671 return scale_changed;
672}
673
674static void update_colorkey(struct intel_overlay *overlay,
675 struct overlay_registers *regs)
676{
677 u32 key = overlay->color_key;
678 switch (overlay->crtc->base.fb->bits_per_pixel) {
Chris Wilson722506f2010-08-12 09:28:50 +0100679 case 8:
680 regs->DCLRKV = 0;
681 regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
682 case 16:
683 if (overlay->crtc->base.fb->depth == 15) {
684 regs->DCLRKV = RGB15_TO_COLORKEY(key);
685 regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
686 } else {
687 regs->DCLRKV = RGB16_TO_COLORKEY(key);
688 regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
689 }
690 case 24:
691 case 32:
692 regs->DCLRKV = key;
693 regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200694 }
695}
696
697static u32 overlay_cmd_reg(struct put_image_params *params)
698{
699 u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
700
701 if (params->format & I915_OVERLAY_YUV_PLANAR) {
702 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +0100703 case I915_OVERLAY_YUV422:
704 cmd |= OCMD_YUV_422_PLANAR;
705 break;
706 case I915_OVERLAY_YUV420:
707 cmd |= OCMD_YUV_420_PLANAR;
708 break;
709 case I915_OVERLAY_YUV411:
710 case I915_OVERLAY_YUV410:
711 cmd |= OCMD_YUV_410_PLANAR;
712 break;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200713 }
714 } else { /* YUV packed */
715 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +0100716 case I915_OVERLAY_YUV422:
717 cmd |= OCMD_YUV_422_PACKED;
718 break;
719 case I915_OVERLAY_YUV411:
720 cmd |= OCMD_YUV_411_PACKED;
721 break;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200722 }
723
724 switch (params->format & I915_OVERLAY_SWAP_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +0100725 case I915_OVERLAY_NO_SWAP:
726 break;
727 case I915_OVERLAY_UV_SWAP:
728 cmd |= OCMD_UV_SWAP;
729 break;
730 case I915_OVERLAY_Y_SWAP:
731 cmd |= OCMD_Y_SWAP;
732 break;
733 case I915_OVERLAY_Y_AND_UV_SWAP:
734 cmd |= OCMD_Y_AND_UV_SWAP;
735 break;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200736 }
737 }
738
739 return cmd;
740}
741
742int intel_overlay_do_put_image(struct intel_overlay *overlay,
743 struct drm_gem_object *new_bo,
744 struct put_image_params *params)
745{
746 int ret, tmp_width;
747 struct overlay_registers *regs;
748 bool scale_changed = false;
Daniel Vetter23010e42010-03-08 13:35:02 +0100749 struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200750 struct drm_device *dev = overlay->dev;
751
752 BUG_ON(!mutex_is_locked(&dev->struct_mutex));
753 BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
754 BUG_ON(!overlay);
755
Daniel Vetter02e792f2009-09-15 22:57:34 +0200756 ret = intel_overlay_release_old_vid(overlay);
757 if (ret != 0)
758 return ret;
759
760 ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
761 if (ret != 0)
762 return ret;
763
764 ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
765 if (ret != 0)
766 goto out_unpin;
767
768 if (!overlay->active) {
769 regs = intel_overlay_map_regs_atomic(overlay);
770 if (!regs) {
771 ret = -ENOMEM;
772 goto out_unpin;
773 }
774 regs->OCONFIG = OCONF_CC_OUT_8BIT;
775 if (IS_I965GM(overlay->dev))
776 regs->OCONFIG |= OCONF_CSC_MODE_BT709;
777 regs->OCONFIG |= overlay->crtc->pipe == 0 ?
778 OCONF_PIPE_A : OCONF_PIPE_B;
779 intel_overlay_unmap_regs_atomic(overlay);
780
781 ret = intel_overlay_on(overlay);
782 if (ret != 0)
783 goto out_unpin;
784 }
785
786 regs = intel_overlay_map_regs_atomic(overlay);
787 if (!regs) {
788 ret = -ENOMEM;
789 goto out_unpin;
790 }
791
792 regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
793 regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
794
795 if (params->format & I915_OVERLAY_YUV_PACKED)
796 tmp_width = packed_width_bytes(params->format, params->src_w);
797 else
798 tmp_width = params->src_w;
799
800 regs->SWIDTH = params->src_w;
801 regs->SWIDTHSW = calc_swidthsw(overlay->dev,
Chris Wilson722506f2010-08-12 09:28:50 +0100802 params->offset_Y, tmp_width);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200803 regs->SHEIGHT = params->src_h;
804 regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
805 regs->OSTRIDE = params->stride_Y;
806
807 if (params->format & I915_OVERLAY_YUV_PLANAR) {
808 int uv_hscale = uv_hsubsampling(params->format);
809 int uv_vscale = uv_vsubsampling(params->format);
810 u32 tmp_U, tmp_V;
811 regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
812 tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
Chris Wilson722506f2010-08-12 09:28:50 +0100813 params->src_w/uv_hscale);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200814 tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
Chris Wilson722506f2010-08-12 09:28:50 +0100815 params->src_w/uv_hscale);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200816 regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
817 regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
818 regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
819 regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
820 regs->OSTRIDE |= params->stride_UV << 16;
821 }
822
823 scale_changed = update_scaling_factors(overlay, regs, params);
824
825 update_colorkey(overlay, regs);
826
827 regs->OCMD = overlay_cmd_reg(params);
828
829 intel_overlay_unmap_regs_atomic(overlay);
830
831 intel_overlay_continue(overlay, scale_changed);
832
833 overlay->old_vid_bo = overlay->vid_bo;
Daniel Vetter23010e42010-03-08 13:35:02 +0100834 overlay->vid_bo = to_intel_bo(new_bo);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200835
836 return 0;
837
838out_unpin:
839 i915_gem_object_unpin(new_bo);
840 return ret;
841}
842
843int intel_overlay_switch_off(struct intel_overlay *overlay)
844{
845 int ret;
846 struct overlay_registers *regs;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200847 struct drm_device *dev = overlay->dev;
848
849 BUG_ON(!mutex_is_locked(&dev->struct_mutex));
850 BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
851
Daniel Vetter9bedb972009-11-30 15:55:49 +0100852 if (overlay->hw_wedged) {
853 ret = intel_overlay_recover_from_interrupt(overlay, 1);
854 if (ret != 0)
855 return ret;
856 }
857
Daniel Vetter02e792f2009-09-15 22:57:34 +0200858 if (!overlay->active)
859 return 0;
860
Daniel Vetter02e792f2009-09-15 22:57:34 +0200861 ret = intel_overlay_release_old_vid(overlay);
862 if (ret != 0)
863 return ret;
864
865 regs = intel_overlay_map_regs_atomic(overlay);
866 regs->OCMD = 0;
867 intel_overlay_unmap_regs_atomic(overlay);
868
869 ret = intel_overlay_off(overlay);
Daniel Vetter03f77ea2009-09-15 22:57:37 +0200870 if (ret != 0)
871 return ret;
872
Daniel Vetter12ca45f2037-04-25 10:08:26 +0200873 intel_overlay_off_tail(overlay);
Daniel Vetter02e792f2009-09-15 22:57:34 +0200874
875 return 0;
876}
877
878static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
879 struct intel_crtc *crtc)
880{
Chris Wilson722506f2010-08-12 09:28:50 +0100881 drm_i915_private_t *dev_priv = overlay->dev->dev_private;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200882 u32 pipeconf;
883 int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
884
885 if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON)
886 return -EINVAL;
887
888 pipeconf = I915_READ(pipeconf_reg);
889
890 /* can't use the overlay with double wide pipe */
891 if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE)
892 return -EINVAL;
893
894 return 0;
895}
896
897static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
898{
899 struct drm_device *dev = overlay->dev;
Chris Wilson722506f2010-08-12 09:28:50 +0100900 drm_i915_private_t *dev_priv = dev->dev_private;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200901 u32 ratio;
902 u32 pfit_control = I915_READ(PFIT_CONTROL);
903
904 /* XXX: This is not the same logic as in the xorg driver, but more in
905 * line with the intel documentation for the i965 */
906 if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) {
907 ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT;
908 } else { /* on i965 use the PGM reg to read out the autoscaler values */
909 ratio = I915_READ(PFIT_PGM_RATIOS);
910 if (IS_I965G(dev))
911 ratio >>= PFIT_VERT_SCALE_SHIFT_965;
912 else
913 ratio >>= PFIT_VERT_SCALE_SHIFT;
914 }
915
916 overlay->pfit_vscale_ratio = ratio;
917}
918
919static int check_overlay_dst(struct intel_overlay *overlay,
920 struct drm_intel_overlay_put_image *rec)
921{
922 struct drm_display_mode *mode = &overlay->crtc->base.mode;
923
Chris Wilson722506f2010-08-12 09:28:50 +0100924 if (rec->dst_x < mode->crtc_hdisplay &&
925 rec->dst_x + rec->dst_width <= mode->crtc_hdisplay &&
926 rec->dst_y < mode->crtc_vdisplay &&
927 rec->dst_y + rec->dst_height <= mode->crtc_vdisplay)
Daniel Vetter02e792f2009-09-15 22:57:34 +0200928 return 0;
929 else
930 return -EINVAL;
931}
932
933static int check_overlay_scaling(struct put_image_params *rec)
934{
935 u32 tmp;
936
937 /* downscaling limit is 8.0 */
938 tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
939 if (tmp > 7)
940 return -EINVAL;
941 tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
942 if (tmp > 7)
943 return -EINVAL;
944
945 return 0;
946}
947
948static int check_overlay_src(struct drm_device *dev,
949 struct drm_intel_overlay_put_image *rec,
950 struct drm_gem_object *new_bo)
951{
952 u32 stride_mask;
953 int depth;
954 int uv_hscale = uv_hsubsampling(rec->flags);
955 int uv_vscale = uv_vsubsampling(rec->flags);
956 size_t tmp;
957
958 /* check src dimensions */
959 if (IS_845G(dev) || IS_I830(dev)) {
Chris Wilson722506f2010-08-12 09:28:50 +0100960 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
961 rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
Daniel Vetter02e792f2009-09-15 22:57:34 +0200962 return -EINVAL;
963 } else {
Chris Wilson722506f2010-08-12 09:28:50 +0100964 if (rec->src_height > IMAGE_MAX_HEIGHT ||
965 rec->src_width > IMAGE_MAX_WIDTH)
Daniel Vetter02e792f2009-09-15 22:57:34 +0200966 return -EINVAL;
967 }
968 /* better safe than sorry, use 4 as the maximal subsampling ratio */
Chris Wilson722506f2010-08-12 09:28:50 +0100969 if (rec->src_height < N_VERT_Y_TAPS*4 ||
970 rec->src_width < N_HORIZ_Y_TAPS*4)
Daniel Vetter02e792f2009-09-15 22:57:34 +0200971 return -EINVAL;
972
Chris Wilsona1efd142010-07-12 19:35:38 +0100973 /* check alignment constraints */
Daniel Vetter02e792f2009-09-15 22:57:34 +0200974 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +0100975 case I915_OVERLAY_RGB:
976 /* not implemented */
977 return -EINVAL;
978 case I915_OVERLAY_YUV_PACKED:
979 depth = packed_depth_bytes(rec->flags);
980 if (uv_vscale != 1)
Daniel Vetter02e792f2009-09-15 22:57:34 +0200981 return -EINVAL;
Chris Wilson722506f2010-08-12 09:28:50 +0100982 if (depth < 0)
983 return depth;
984 /* ignore UV planes */
985 rec->stride_UV = 0;
986 rec->offset_U = 0;
987 rec->offset_V = 0;
988 /* check pixel alignment */
989 if (rec->offset_Y % depth)
Daniel Vetter02e792f2009-09-15 22:57:34 +0200990 return -EINVAL;
Chris Wilson722506f2010-08-12 09:28:50 +0100991 break;
992 case I915_OVERLAY_YUV_PLANAR:
993 if (uv_vscale < 0 || uv_hscale < 0)
994 return -EINVAL;
995 /* no offset restrictions for planar formats */
996 break;
997 default:
998 return -EINVAL;
Daniel Vetter02e792f2009-09-15 22:57:34 +0200999 }
1000
1001 if (rec->src_width % uv_hscale)
1002 return -EINVAL;
1003
1004 /* stride checking */
Chris Wilsona1efd142010-07-12 19:35:38 +01001005 if (IS_I830(dev) || IS_845G(dev))
1006 stride_mask = 255;
1007 else
1008 stride_mask = 63;
Daniel Vetter02e792f2009-09-15 22:57:34 +02001009
1010 if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
1011 return -EINVAL;
1012 if (IS_I965G(dev) && rec->stride_Y < 512)
1013 return -EINVAL;
1014
1015 tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
1016 4 : 8;
1017 if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024)
1018 return -EINVAL;
1019
1020 /* check buffer dimensions */
1021 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
Chris Wilson722506f2010-08-12 09:28:50 +01001022 case I915_OVERLAY_RGB:
1023 case I915_OVERLAY_YUV_PACKED:
1024 /* always 4 Y values per depth pixels */
1025 if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1026 return -EINVAL;
Daniel Vetter02e792f2009-09-15 22:57:34 +02001027
Chris Wilson722506f2010-08-12 09:28:50 +01001028 tmp = rec->stride_Y*rec->src_height;
1029 if (rec->offset_Y + tmp > new_bo->size)
1030 return -EINVAL;
1031 break;
Daniel Vetter02e792f2009-09-15 22:57:34 +02001032
Chris Wilson722506f2010-08-12 09:28:50 +01001033 case I915_OVERLAY_YUV_PLANAR:
1034 if (rec->src_width > rec->stride_Y)
1035 return -EINVAL;
1036 if (rec->src_width/uv_hscale > rec->stride_UV)
1037 return -EINVAL;
1038
1039 tmp = rec->stride_Y*rec->src_height;
1040 if (rec->offset_Y + tmp > new_bo->size)
1041 return -EINVAL;
1042 tmp = rec->stride_UV*rec->src_height;
1043 tmp /= uv_vscale;
1044 if (rec->offset_U + tmp > new_bo->size ||
1045 rec->offset_V + tmp > new_bo->size)
1046 return -EINVAL;
1047 break;
Daniel Vetter02e792f2009-09-15 22:57:34 +02001048 }
1049
1050 return 0;
1051}
1052
1053int intel_overlay_put_image(struct drm_device *dev, void *data,
1054 struct drm_file *file_priv)
1055{
1056 struct drm_intel_overlay_put_image *put_image_rec = data;
1057 drm_i915_private_t *dev_priv = dev->dev_private;
1058 struct intel_overlay *overlay;
1059 struct drm_mode_object *drmmode_obj;
1060 struct intel_crtc *crtc;
1061 struct drm_gem_object *new_bo;
1062 struct put_image_params *params;
1063 int ret;
1064
1065 if (!dev_priv) {
1066 DRM_ERROR("called with no initialization\n");
1067 return -EINVAL;
1068 }
1069
1070 overlay = dev_priv->overlay;
1071 if (!overlay) {
1072 DRM_DEBUG("userspace bug: no overlay\n");
1073 return -ENODEV;
1074 }
1075
1076 if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
1077 mutex_lock(&dev->mode_config.mutex);
1078 mutex_lock(&dev->struct_mutex);
1079
1080 ret = intel_overlay_switch_off(overlay);
1081
1082 mutex_unlock(&dev->struct_mutex);
1083 mutex_unlock(&dev->mode_config.mutex);
1084
1085 return ret;
1086 }
1087
1088 params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
1089 if (!params)
1090 return -ENOMEM;
1091
1092 drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
Chris Wilson722506f2010-08-12 09:28:50 +01001093 DRM_MODE_OBJECT_CRTC);
Dan Carpenter915a4282010-03-06 14:05:39 +03001094 if (!drmmode_obj) {
1095 ret = -ENOENT;
1096 goto out_free;
1097 }
Daniel Vetter02e792f2009-09-15 22:57:34 +02001098 crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
1099
1100 new_bo = drm_gem_object_lookup(dev, file_priv,
Chris Wilson722506f2010-08-12 09:28:50 +01001101 put_image_rec->bo_handle);
Dan Carpenter915a4282010-03-06 14:05:39 +03001102 if (!new_bo) {
1103 ret = -ENOENT;
1104 goto out_free;
1105 }
Daniel Vetter02e792f2009-09-15 22:57:34 +02001106
1107 mutex_lock(&dev->mode_config.mutex);
1108 mutex_lock(&dev->struct_mutex);
1109
Daniel Vetter03f77ea2009-09-15 22:57:37 +02001110 if (overlay->hw_wedged) {
1111 ret = intel_overlay_recover_from_interrupt(overlay, 1);
1112 if (ret != 0)
1113 goto out_unlock;
1114 }
1115
Daniel Vetter02e792f2009-09-15 22:57:34 +02001116 if (overlay->crtc != crtc) {
1117 struct drm_display_mode *mode = &crtc->base.mode;
1118 ret = intel_overlay_switch_off(overlay);
1119 if (ret != 0)
1120 goto out_unlock;
1121
1122 ret = check_overlay_possible_on_crtc(overlay, crtc);
1123 if (ret != 0)
1124 goto out_unlock;
1125
1126 overlay->crtc = crtc;
1127 crtc->overlay = overlay;
1128
1129 if (intel_panel_fitter_pipe(dev) == crtc->pipe
1130 /* and line to wide, i.e. one-line-mode */
1131 && mode->hdisplay > 1024) {
1132 overlay->pfit_active = 1;
1133 update_pfit_vscale_ratio(overlay);
1134 } else
1135 overlay->pfit_active = 0;
1136 }
1137
1138 ret = check_overlay_dst(overlay, put_image_rec);
1139 if (ret != 0)
1140 goto out_unlock;
1141
1142 if (overlay->pfit_active) {
1143 params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
Chris Wilson722506f2010-08-12 09:28:50 +01001144 overlay->pfit_vscale_ratio);
Daniel Vetter02e792f2009-09-15 22:57:34 +02001145 /* shifting right rounds downwards, so add 1 */
1146 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
Chris Wilson722506f2010-08-12 09:28:50 +01001147 overlay->pfit_vscale_ratio) + 1;
Daniel Vetter02e792f2009-09-15 22:57:34 +02001148 } else {
1149 params->dst_y = put_image_rec->dst_y;
1150 params->dst_h = put_image_rec->dst_height;
1151 }
1152 params->dst_x = put_image_rec->dst_x;
1153 params->dst_w = put_image_rec->dst_width;
1154
1155 params->src_w = put_image_rec->src_width;
1156 params->src_h = put_image_rec->src_height;
1157 params->src_scan_w = put_image_rec->src_scan_width;
1158 params->src_scan_h = put_image_rec->src_scan_height;
Chris Wilson722506f2010-08-12 09:28:50 +01001159 if (params->src_scan_h > params->src_h ||
1160 params->src_scan_w > params->src_w) {
Daniel Vetter02e792f2009-09-15 22:57:34 +02001161 ret = -EINVAL;
1162 goto out_unlock;
1163 }
1164
1165 ret = check_overlay_src(dev, put_image_rec, new_bo);
1166 if (ret != 0)
1167 goto out_unlock;
1168 params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
1169 params->stride_Y = put_image_rec->stride_Y;
1170 params->stride_UV = put_image_rec->stride_UV;
1171 params->offset_Y = put_image_rec->offset_Y;
1172 params->offset_U = put_image_rec->offset_U;
1173 params->offset_V = put_image_rec->offset_V;
1174
1175 /* Check scaling after src size to prevent a divide-by-zero. */
1176 ret = check_overlay_scaling(params);
1177 if (ret != 0)
1178 goto out_unlock;
1179
1180 ret = intel_overlay_do_put_image(overlay, new_bo, params);
1181 if (ret != 0)
1182 goto out_unlock;
1183
1184 mutex_unlock(&dev->struct_mutex);
1185 mutex_unlock(&dev->mode_config.mutex);
1186
1187 kfree(params);
1188
1189 return 0;
1190
1191out_unlock:
1192 mutex_unlock(&dev->struct_mutex);
1193 mutex_unlock(&dev->mode_config.mutex);
Luca Barbieribc9025b2010-02-09 05:49:12 +00001194 drm_gem_object_unreference_unlocked(new_bo);
Dan Carpenter915a4282010-03-06 14:05:39 +03001195out_free:
Daniel Vetter02e792f2009-09-15 22:57:34 +02001196 kfree(params);
1197
1198 return ret;
1199}
1200
1201static void update_reg_attrs(struct intel_overlay *overlay,
1202 struct overlay_registers *regs)
1203{
1204 regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
1205 regs->OCLRC1 = overlay->saturation;
1206}
1207
1208static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
1209{
1210 int i;
1211
1212 if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
1213 return false;
1214
1215 for (i = 0; i < 3; i++) {
Chris Wilson722506f2010-08-12 09:28:50 +01001216 if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
Daniel Vetter02e792f2009-09-15 22:57:34 +02001217 return false;
1218 }
1219
1220 return true;
1221}
1222
1223static bool check_gamma5_errata(u32 gamma5)
1224{
1225 int i;
1226
1227 for (i = 0; i < 3; i++) {
1228 if (((gamma5 >> i*8) & 0xff) == 0x80)
1229 return false;
1230 }
1231
1232 return true;
1233}
1234
1235static int check_gamma(struct drm_intel_overlay_attrs *attrs)
1236{
Chris Wilson722506f2010-08-12 09:28:50 +01001237 if (!check_gamma_bounds(0, attrs->gamma0) ||
1238 !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1239 !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1240 !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1241 !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1242 !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1243 !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
Daniel Vetter02e792f2009-09-15 22:57:34 +02001244 return -EINVAL;
Chris Wilson722506f2010-08-12 09:28:50 +01001245
Daniel Vetter02e792f2009-09-15 22:57:34 +02001246 if (!check_gamma5_errata(attrs->gamma5))
1247 return -EINVAL;
Chris Wilson722506f2010-08-12 09:28:50 +01001248
Daniel Vetter02e792f2009-09-15 22:57:34 +02001249 return 0;
1250}
1251
1252int intel_overlay_attrs(struct drm_device *dev, void *data,
1253 struct drm_file *file_priv)
1254{
1255 struct drm_intel_overlay_attrs *attrs = data;
1256 drm_i915_private_t *dev_priv = dev->dev_private;
1257 struct intel_overlay *overlay;
1258 struct overlay_registers *regs;
1259 int ret;
1260
1261 if (!dev_priv) {
1262 DRM_ERROR("called with no initialization\n");
1263 return -EINVAL;
1264 }
1265
1266 overlay = dev_priv->overlay;
1267 if (!overlay) {
1268 DRM_DEBUG("userspace bug: no overlay\n");
1269 return -ENODEV;
1270 }
1271
1272 mutex_lock(&dev->mode_config.mutex);
1273 mutex_lock(&dev->struct_mutex);
1274
1275 if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
1276 attrs->color_key = overlay->color_key;
1277 attrs->brightness = overlay->brightness;
1278 attrs->contrast = overlay->contrast;
1279 attrs->saturation = overlay->saturation;
1280
1281 if (IS_I9XX(dev)) {
1282 attrs->gamma0 = I915_READ(OGAMC0);
1283 attrs->gamma1 = I915_READ(OGAMC1);
1284 attrs->gamma2 = I915_READ(OGAMC2);
1285 attrs->gamma3 = I915_READ(OGAMC3);
1286 attrs->gamma4 = I915_READ(OGAMC4);
1287 attrs->gamma5 = I915_READ(OGAMC5);
1288 }
1289 ret = 0;
1290 } else {
1291 overlay->color_key = attrs->color_key;
1292 if (attrs->brightness >= -128 && attrs->brightness <= 127) {
1293 overlay->brightness = attrs->brightness;
1294 } else {
1295 ret = -EINVAL;
1296 goto out_unlock;
1297 }
Chris Wilson722506f2010-08-12 09:28:50 +01001298
Daniel Vetter02e792f2009-09-15 22:57:34 +02001299 if (attrs->contrast <= 255) {
1300 overlay->contrast = attrs->contrast;
1301 } else {
1302 ret = -EINVAL;
1303 goto out_unlock;
1304 }
Chris Wilson722506f2010-08-12 09:28:50 +01001305
Daniel Vetter02e792f2009-09-15 22:57:34 +02001306 if (attrs->saturation <= 1023) {
1307 overlay->saturation = attrs->saturation;
1308 } else {
1309 ret = -EINVAL;
1310 goto out_unlock;
1311 }
1312
1313 regs = intel_overlay_map_regs_atomic(overlay);
1314 if (!regs) {
1315 ret = -ENOMEM;
1316 goto out_unlock;
1317 }
1318
1319 update_reg_attrs(overlay, regs);
1320
1321 intel_overlay_unmap_regs_atomic(overlay);
1322
1323 if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1324 if (!IS_I9XX(dev)) {
1325 ret = -EINVAL;
1326 goto out_unlock;
1327 }
1328
1329 if (overlay->active) {
1330 ret = -EBUSY;
1331 goto out_unlock;
1332 }
1333
1334 ret = check_gamma(attrs);
1335 if (ret != 0)
1336 goto out_unlock;
1337
1338 I915_WRITE(OGAMC0, attrs->gamma0);
1339 I915_WRITE(OGAMC1, attrs->gamma1);
1340 I915_WRITE(OGAMC2, attrs->gamma2);
1341 I915_WRITE(OGAMC3, attrs->gamma3);
1342 I915_WRITE(OGAMC4, attrs->gamma4);
1343 I915_WRITE(OGAMC5, attrs->gamma5);
1344 }
1345 ret = 0;
1346 }
1347
1348out_unlock:
1349 mutex_unlock(&dev->struct_mutex);
1350 mutex_unlock(&dev->mode_config.mutex);
1351
1352 return ret;
1353}
1354
1355void intel_setup_overlay(struct drm_device *dev)
1356{
1357 drm_i915_private_t *dev_priv = dev->dev_private;
1358 struct intel_overlay *overlay;
1359 struct drm_gem_object *reg_bo;
1360 struct overlay_registers *regs;
1361 int ret;
1362
1363 if (!OVERLAY_EXISTS(dev))
1364 return;
1365
1366 overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
1367 if (!overlay)
1368 return;
1369 overlay->dev = dev;
1370
Daniel Vetterac52bc52010-04-09 19:05:06 +00001371 reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
Daniel Vetter02e792f2009-09-15 22:57:34 +02001372 if (!reg_bo)
1373 goto out_free;
Daniel Vetter23010e42010-03-08 13:35:02 +01001374 overlay->reg_bo = to_intel_bo(reg_bo);
Daniel Vetter02e792f2009-09-15 22:57:34 +02001375
1376 if (OVERLAY_NONPHYSICAL(dev)) {
1377 ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
1378 if (ret) {
1379 DRM_ERROR("failed to pin overlay register bo\n");
1380 goto out_free_bo;
1381 }
1382 overlay->flip_addr = overlay->reg_bo->gtt_offset;
1383 } else {
1384 ret = i915_gem_attach_phys_object(dev, reg_bo,
Chris Wilson6eeefaf2010-08-07 11:01:39 +01001385 I915_GEM_PHYS_OVERLAY_REGS,
1386 0);
Daniel Vetter02e792f2009-09-15 22:57:34 +02001387 if (ret) {
1388 DRM_ERROR("failed to attach phys overlay regs\n");
1389 goto out_free_bo;
1390 }
1391 overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
1392 }
1393
1394 /* init all values */
1395 overlay->color_key = 0x0101fe;
1396 overlay->brightness = -19;
1397 overlay->contrast = 75;
1398 overlay->saturation = 146;
1399
1400 regs = intel_overlay_map_regs_atomic(overlay);
1401 if (!regs)
1402 goto out_free_bo;
1403
1404 memset(regs, 0, sizeof(struct overlay_registers));
1405 update_polyphase_filter(regs);
1406
1407 update_reg_attrs(overlay, regs);
1408
1409 intel_overlay_unmap_regs_atomic(overlay);
1410
1411 dev_priv->overlay = overlay;
1412 DRM_INFO("initialized overlay support\n");
1413 return;
1414
1415out_free_bo:
1416 drm_gem_object_unreference(reg_bo);
1417out_free:
1418 kfree(overlay);
1419 return;
1420}
1421
1422void intel_cleanup_overlay(struct drm_device *dev)
1423{
Chris Wilson722506f2010-08-12 09:28:50 +01001424 drm_i915_private_t *dev_priv = dev->dev_private;
Daniel Vetter02e792f2009-09-15 22:57:34 +02001425
1426 if (dev_priv->overlay) {
1427 /* The bo's should be free'd by the generic code already.
1428 * Furthermore modesetting teardown happens beforehand so the
1429 * hardware should be off already */
1430 BUG_ON(dev_priv->overlay->active);
1431
1432 kfree(dev_priv->overlay);
1433 }
1434}
Chris Wilson6ef3d422010-08-04 20:26:07 +01001435
1436struct intel_overlay_error_state {
1437 struct overlay_registers regs;
1438 unsigned long base;
1439 u32 dovsta;
1440 u32 isr;
1441};
1442
1443struct intel_overlay_error_state *
1444intel_overlay_capture_error_state(struct drm_device *dev)
1445{
1446 drm_i915_private_t *dev_priv = dev->dev_private;
1447 struct intel_overlay *overlay = dev_priv->overlay;
1448 struct intel_overlay_error_state *error;
1449 struct overlay_registers __iomem *regs;
1450
1451 if (!overlay || !overlay->active)
1452 return NULL;
1453
1454 error = kmalloc(sizeof(*error), GFP_ATOMIC);
1455 if (error == NULL)
1456 return NULL;
1457
1458 error->dovsta = I915_READ(DOVSTA);
1459 error->isr = I915_READ(ISR);
1460 if (OVERLAY_NONPHYSICAL(overlay->dev))
1461 error->base = (long) overlay->reg_bo->gtt_offset;
1462 else
1463 error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
1464
1465 regs = intel_overlay_map_regs_atomic(overlay);
1466 if (!regs)
1467 goto err;
1468
1469 memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
1470 intel_overlay_unmap_regs_atomic(overlay);
1471
1472 return error;
1473
1474err:
1475 kfree(error);
1476 return NULL;
1477}
1478
1479void
1480intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
1481{
1482 seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
1483 error->dovsta, error->isr);
1484 seq_printf(m, " Register file at 0x%08lx:\n",
1485 error->base);
1486
1487#define P(x) seq_printf(m, " " #x ": 0x%08x\n", error->regs.x)
1488 P(OBUF_0Y);
1489 P(OBUF_1Y);
1490 P(OBUF_0U);
1491 P(OBUF_0V);
1492 P(OBUF_1U);
1493 P(OBUF_1V);
1494 P(OSTRIDE);
1495 P(YRGB_VPH);
1496 P(UV_VPH);
1497 P(HORZ_PH);
1498 P(INIT_PHS);
1499 P(DWINPOS);
1500 P(DWINSZ);
1501 P(SWIDTH);
1502 P(SWIDTHSW);
1503 P(SHEIGHT);
1504 P(YRGBSCALE);
1505 P(UVSCALE);
1506 P(OCLRC0);
1507 P(OCLRC1);
1508 P(DCLRKV);
1509 P(DCLRKM);
1510 P(SCLRKVH);
1511 P(SCLRKVL);
1512 P(SCLRKEN);
1513 P(OCONFIG);
1514 P(OCMD);
1515 P(OSTART_0Y);
1516 P(OSTART_1Y);
1517 P(OSTART_0U);
1518 P(OSTART_0V);
1519 P(OSTART_1U);
1520 P(OSTART_1V);
1521 P(OTILEOFF_0Y);
1522 P(OTILEOFF_1Y);
1523 P(OTILEOFF_0U);
1524 P(OTILEOFF_0V);
1525 P(OTILEOFF_1U);
1526 P(OTILEOFF_1V);
1527 P(FASTHSCALE);
1528 P(UVSCALEV);
1529#undef P
1530}