Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/gpu/drm/i915/intel_overlay.c
15113 views
1
/*
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 <[email protected]>
25
*
26
* Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
27
*/
28
29
#include <linux/seq_file.h>
30
#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)
70
#define OCMD_BUF_TYPE_MASK (0x1<<5)
71
#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 */
119
struct 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
struct intel_overlay {
174
struct drm_device *dev;
175
struct intel_crtc *crtc;
176
struct drm_i915_gem_object *vid_bo;
177
struct drm_i915_gem_object *old_vid_bo;
178
int active;
179
int pfit_active;
180
u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
181
u32 color_key;
182
u32 brightness, contrast, saturation;
183
u32 old_xscale, old_yscale;
184
/* register access */
185
u32 flip_addr;
186
struct drm_i915_gem_object *reg_bo;
187
/* flip handling */
188
uint32_t last_flip_req;
189
void (*flip_tail)(struct intel_overlay *);
190
};
191
192
static struct overlay_registers *
193
intel_overlay_map_regs(struct intel_overlay *overlay)
194
{
195
drm_i915_private_t *dev_priv = overlay->dev->dev_private;
196
struct overlay_registers *regs;
197
198
if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
199
regs = overlay->reg_bo->phys_obj->handle->vaddr;
200
else
201
regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping,
202
overlay->reg_bo->gtt_offset);
203
204
return regs;
205
}
206
207
static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
208
struct overlay_registers *regs)
209
{
210
if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
211
io_mapping_unmap(regs);
212
}
213
214
static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
215
struct drm_i915_gem_request *request,
216
void (*tail)(struct intel_overlay *))
217
{
218
struct drm_device *dev = overlay->dev;
219
drm_i915_private_t *dev_priv = dev->dev_private;
220
int ret;
221
222
BUG_ON(overlay->last_flip_req);
223
ret = i915_add_request(LP_RING(dev_priv), NULL, request);
224
if (ret) {
225
kfree(request);
226
return ret;
227
}
228
overlay->last_flip_req = request->seqno;
229
overlay->flip_tail = tail;
230
ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req);
231
if (ret)
232
return ret;
233
234
overlay->last_flip_req = 0;
235
return 0;
236
}
237
238
/* Workaround for i830 bug where pipe a must be enable to change control regs */
239
static int
240
i830_activate_pipe_a(struct drm_device *dev)
241
{
242
drm_i915_private_t *dev_priv = dev->dev_private;
243
struct intel_crtc *crtc;
244
struct drm_crtc_helper_funcs *crtc_funcs;
245
struct drm_display_mode vesa_640x480 = {
246
DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
247
752, 800, 0, 480, 489, 492, 525, 0,
248
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
249
}, *mode;
250
251
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]);
252
if (crtc->dpms_mode == DRM_MODE_DPMS_ON)
253
return 0;
254
255
/* most i8xx have pipe a forced on, so don't trust dpms mode */
256
if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE)
257
return 0;
258
259
crtc_funcs = crtc->base.helper_private;
260
if (crtc_funcs->dpms == NULL)
261
return 0;
262
263
DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
264
265
mode = drm_mode_duplicate(dev, &vesa_640x480);
266
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
267
if(!drm_crtc_helper_set_mode(&crtc->base, mode,
268
crtc->base.x, crtc->base.y,
269
crtc->base.fb))
270
return 0;
271
272
crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON);
273
return 1;
274
}
275
276
static void
277
i830_deactivate_pipe_a(struct drm_device *dev)
278
{
279
drm_i915_private_t *dev_priv = dev->dev_private;
280
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
281
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
282
283
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
284
}
285
286
/* overlay needs to be disable in OCMD reg */
287
static int intel_overlay_on(struct intel_overlay *overlay)
288
{
289
struct drm_device *dev = overlay->dev;
290
struct drm_i915_private *dev_priv = dev->dev_private;
291
struct drm_i915_gem_request *request;
292
int pipe_a_quirk = 0;
293
int ret;
294
295
BUG_ON(overlay->active);
296
overlay->active = 1;
297
298
if (IS_I830(dev)) {
299
pipe_a_quirk = i830_activate_pipe_a(dev);
300
if (pipe_a_quirk < 0)
301
return pipe_a_quirk;
302
}
303
304
request = kzalloc(sizeof(*request), GFP_KERNEL);
305
if (request == NULL) {
306
ret = -ENOMEM;
307
goto out;
308
}
309
310
ret = BEGIN_LP_RING(4);
311
if (ret) {
312
kfree(request);
313
goto out;
314
}
315
316
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
317
OUT_RING(overlay->flip_addr | OFC_UPDATE);
318
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
319
OUT_RING(MI_NOOP);
320
ADVANCE_LP_RING();
321
322
ret = intel_overlay_do_wait_request(overlay, request, NULL);
323
out:
324
if (pipe_a_quirk)
325
i830_deactivate_pipe_a(dev);
326
327
return ret;
328
}
329
330
/* overlay needs to be enabled in OCMD reg */
331
static int intel_overlay_continue(struct intel_overlay *overlay,
332
bool load_polyphase_filter)
333
{
334
struct drm_device *dev = overlay->dev;
335
drm_i915_private_t *dev_priv = dev->dev_private;
336
struct drm_i915_gem_request *request;
337
u32 flip_addr = overlay->flip_addr;
338
u32 tmp;
339
int ret;
340
341
BUG_ON(!overlay->active);
342
343
request = kzalloc(sizeof(*request), GFP_KERNEL);
344
if (request == NULL)
345
return -ENOMEM;
346
347
if (load_polyphase_filter)
348
flip_addr |= OFC_UPDATE;
349
350
/* check for underruns */
351
tmp = I915_READ(DOVSTA);
352
if (tmp & (1 << 17))
353
DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
354
355
ret = BEGIN_LP_RING(2);
356
if (ret) {
357
kfree(request);
358
return ret;
359
}
360
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
361
OUT_RING(flip_addr);
362
ADVANCE_LP_RING();
363
364
ret = i915_add_request(LP_RING(dev_priv), NULL, request);
365
if (ret) {
366
kfree(request);
367
return ret;
368
}
369
370
overlay->last_flip_req = request->seqno;
371
return 0;
372
}
373
374
static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
375
{
376
struct drm_i915_gem_object *obj = overlay->old_vid_bo;
377
378
i915_gem_object_unpin(obj);
379
drm_gem_object_unreference(&obj->base);
380
381
overlay->old_vid_bo = NULL;
382
}
383
384
static void intel_overlay_off_tail(struct intel_overlay *overlay)
385
{
386
struct drm_i915_gem_object *obj = overlay->vid_bo;
387
388
/* never have the overlay hw on without showing a frame */
389
BUG_ON(!overlay->vid_bo);
390
391
i915_gem_object_unpin(obj);
392
drm_gem_object_unreference(&obj->base);
393
overlay->vid_bo = NULL;
394
395
overlay->crtc->overlay = NULL;
396
overlay->crtc = NULL;
397
overlay->active = 0;
398
}
399
400
/* overlay needs to be disabled in OCMD reg */
401
static int intel_overlay_off(struct intel_overlay *overlay)
402
{
403
struct drm_device *dev = overlay->dev;
404
struct drm_i915_private *dev_priv = dev->dev_private;
405
u32 flip_addr = overlay->flip_addr;
406
struct drm_i915_gem_request *request;
407
int ret;
408
409
BUG_ON(!overlay->active);
410
411
request = kzalloc(sizeof(*request), GFP_KERNEL);
412
if (request == NULL)
413
return -ENOMEM;
414
415
/* According to intel docs the overlay hw may hang (when switching
416
* off) without loading the filter coeffs. It is however unclear whether
417
* this applies to the disabling of the overlay or to the switching off
418
* of the hw. Do it in both cases */
419
flip_addr |= OFC_UPDATE;
420
421
ret = BEGIN_LP_RING(6);
422
if (ret) {
423
kfree(request);
424
return ret;
425
}
426
/* wait for overlay to go idle */
427
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
428
OUT_RING(flip_addr);
429
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
430
/* turn overlay off */
431
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
432
OUT_RING(flip_addr);
433
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
434
ADVANCE_LP_RING();
435
436
return intel_overlay_do_wait_request(overlay, request,
437
intel_overlay_off_tail);
438
}
439
440
/* recover from an interruption due to a signal
441
* We have to be careful not to repeat work forever an make forward progess. */
442
static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
443
{
444
struct drm_device *dev = overlay->dev;
445
drm_i915_private_t *dev_priv = dev->dev_private;
446
int ret;
447
448
if (overlay->last_flip_req == 0)
449
return 0;
450
451
ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req);
452
if (ret)
453
return ret;
454
455
if (overlay->flip_tail)
456
overlay->flip_tail(overlay);
457
458
overlay->last_flip_req = 0;
459
return 0;
460
}
461
462
/* Wait for pending overlay flip and release old frame.
463
* Needs to be called before the overlay register are changed
464
* via intel_overlay_(un)map_regs
465
*/
466
static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
467
{
468
struct drm_device *dev = overlay->dev;
469
drm_i915_private_t *dev_priv = dev->dev_private;
470
int ret;
471
472
/* Only wait if there is actually an old frame to release to
473
* guarantee forward progress.
474
*/
475
if (!overlay->old_vid_bo)
476
return 0;
477
478
if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
479
struct drm_i915_gem_request *request;
480
481
/* synchronous slowpath */
482
request = kzalloc(sizeof(*request), GFP_KERNEL);
483
if (request == NULL)
484
return -ENOMEM;
485
486
ret = BEGIN_LP_RING(2);
487
if (ret) {
488
kfree(request);
489
return ret;
490
}
491
492
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
493
OUT_RING(MI_NOOP);
494
ADVANCE_LP_RING();
495
496
ret = intel_overlay_do_wait_request(overlay, request,
497
intel_overlay_release_old_vid_tail);
498
if (ret)
499
return ret;
500
}
501
502
intel_overlay_release_old_vid_tail(overlay);
503
return 0;
504
}
505
506
struct put_image_params {
507
int format;
508
short dst_x;
509
short dst_y;
510
short dst_w;
511
short dst_h;
512
short src_w;
513
short src_scan_h;
514
short src_scan_w;
515
short src_h;
516
short stride_Y;
517
short stride_UV;
518
int offset_Y;
519
int offset_U;
520
int offset_V;
521
};
522
523
static int packed_depth_bytes(u32 format)
524
{
525
switch (format & I915_OVERLAY_DEPTH_MASK) {
526
case I915_OVERLAY_YUV422:
527
return 4;
528
case I915_OVERLAY_YUV411:
529
/* return 6; not implemented */
530
default:
531
return -EINVAL;
532
}
533
}
534
535
static int packed_width_bytes(u32 format, short width)
536
{
537
switch (format & I915_OVERLAY_DEPTH_MASK) {
538
case I915_OVERLAY_YUV422:
539
return width << 1;
540
default:
541
return -EINVAL;
542
}
543
}
544
545
static int uv_hsubsampling(u32 format)
546
{
547
switch (format & I915_OVERLAY_DEPTH_MASK) {
548
case I915_OVERLAY_YUV422:
549
case I915_OVERLAY_YUV420:
550
return 2;
551
case I915_OVERLAY_YUV411:
552
case I915_OVERLAY_YUV410:
553
return 4;
554
default:
555
return -EINVAL;
556
}
557
}
558
559
static int uv_vsubsampling(u32 format)
560
{
561
switch (format & I915_OVERLAY_DEPTH_MASK) {
562
case I915_OVERLAY_YUV420:
563
case I915_OVERLAY_YUV410:
564
return 2;
565
case I915_OVERLAY_YUV422:
566
case I915_OVERLAY_YUV411:
567
return 1;
568
default:
569
return -EINVAL;
570
}
571
}
572
573
static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
574
{
575
u32 mask, shift, ret;
576
if (IS_GEN2(dev)) {
577
mask = 0x1f;
578
shift = 5;
579
} else {
580
mask = 0x3f;
581
shift = 6;
582
}
583
ret = ((offset + width + mask) >> shift) - (offset >> shift);
584
if (!IS_GEN2(dev))
585
ret <<= 1;
586
ret -=1;
587
return ret << 2;
588
}
589
590
static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
591
0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
592
0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
593
0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
594
0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
595
0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
596
0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
597
0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
598
0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
599
0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
600
0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
601
0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
602
0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
603
0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
604
0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
605
0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
606
0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
607
0xb000, 0x3000, 0x0800, 0x3000, 0xb000
608
};
609
610
static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
611
0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
612
0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
613
0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
614
0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
615
0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
616
0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
617
0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
618
0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
619
0x3000, 0x0800, 0x3000
620
};
621
622
static void update_polyphase_filter(struct overlay_registers *regs)
623
{
624
memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
625
memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
626
}
627
628
static bool update_scaling_factors(struct intel_overlay *overlay,
629
struct overlay_registers *regs,
630
struct put_image_params *params)
631
{
632
/* fixed point with a 12 bit shift */
633
u32 xscale, yscale, xscale_UV, yscale_UV;
634
#define FP_SHIFT 12
635
#define FRACT_MASK 0xfff
636
bool scale_changed = false;
637
int uv_hscale = uv_hsubsampling(params->format);
638
int uv_vscale = uv_vsubsampling(params->format);
639
640
if (params->dst_w > 1)
641
xscale = ((params->src_scan_w - 1) << FP_SHIFT)
642
/(params->dst_w);
643
else
644
xscale = 1 << FP_SHIFT;
645
646
if (params->dst_h > 1)
647
yscale = ((params->src_scan_h - 1) << FP_SHIFT)
648
/(params->dst_h);
649
else
650
yscale = 1 << FP_SHIFT;
651
652
/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
653
xscale_UV = xscale/uv_hscale;
654
yscale_UV = yscale/uv_vscale;
655
/* make the Y scale to UV scale ratio an exact multiply */
656
xscale = xscale_UV * uv_hscale;
657
yscale = yscale_UV * uv_vscale;
658
/*} else {
659
xscale_UV = 0;
660
yscale_UV = 0;
661
}*/
662
663
if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
664
scale_changed = true;
665
overlay->old_xscale = xscale;
666
overlay->old_yscale = yscale;
667
668
regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
669
((xscale >> FP_SHIFT) << 16) |
670
((xscale & FRACT_MASK) << 3));
671
672
regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
673
((xscale_UV >> FP_SHIFT) << 16) |
674
((xscale_UV & FRACT_MASK) << 3));
675
676
regs->UVSCALEV = ((((yscale >> FP_SHIFT) << 16) |
677
((yscale_UV >> FP_SHIFT) << 0)));
678
679
if (scale_changed)
680
update_polyphase_filter(regs);
681
682
return scale_changed;
683
}
684
685
static void update_colorkey(struct intel_overlay *overlay,
686
struct overlay_registers *regs)
687
{
688
u32 key = overlay->color_key;
689
690
switch (overlay->crtc->base.fb->bits_per_pixel) {
691
case 8:
692
regs->DCLRKV = 0;
693
regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
694
break;
695
696
case 16:
697
if (overlay->crtc->base.fb->depth == 15) {
698
regs->DCLRKV = RGB15_TO_COLORKEY(key);
699
regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
700
} else {
701
regs->DCLRKV = RGB16_TO_COLORKEY(key);
702
regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
703
}
704
break;
705
706
case 24:
707
case 32:
708
regs->DCLRKV = key;
709
regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
710
break;
711
}
712
}
713
714
static u32 overlay_cmd_reg(struct put_image_params *params)
715
{
716
u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
717
718
if (params->format & I915_OVERLAY_YUV_PLANAR) {
719
switch (params->format & I915_OVERLAY_DEPTH_MASK) {
720
case I915_OVERLAY_YUV422:
721
cmd |= OCMD_YUV_422_PLANAR;
722
break;
723
case I915_OVERLAY_YUV420:
724
cmd |= OCMD_YUV_420_PLANAR;
725
break;
726
case I915_OVERLAY_YUV411:
727
case I915_OVERLAY_YUV410:
728
cmd |= OCMD_YUV_410_PLANAR;
729
break;
730
}
731
} else { /* YUV packed */
732
switch (params->format & I915_OVERLAY_DEPTH_MASK) {
733
case I915_OVERLAY_YUV422:
734
cmd |= OCMD_YUV_422_PACKED;
735
break;
736
case I915_OVERLAY_YUV411:
737
cmd |= OCMD_YUV_411_PACKED;
738
break;
739
}
740
741
switch (params->format & I915_OVERLAY_SWAP_MASK) {
742
case I915_OVERLAY_NO_SWAP:
743
break;
744
case I915_OVERLAY_UV_SWAP:
745
cmd |= OCMD_UV_SWAP;
746
break;
747
case I915_OVERLAY_Y_SWAP:
748
cmd |= OCMD_Y_SWAP;
749
break;
750
case I915_OVERLAY_Y_AND_UV_SWAP:
751
cmd |= OCMD_Y_AND_UV_SWAP;
752
break;
753
}
754
}
755
756
return cmd;
757
}
758
759
static int intel_overlay_do_put_image(struct intel_overlay *overlay,
760
struct drm_i915_gem_object *new_bo,
761
struct put_image_params *params)
762
{
763
int ret, tmp_width;
764
struct overlay_registers *regs;
765
bool scale_changed = false;
766
struct drm_device *dev = overlay->dev;
767
768
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
769
BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
770
BUG_ON(!overlay);
771
772
ret = intel_overlay_release_old_vid(overlay);
773
if (ret != 0)
774
return ret;
775
776
ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true);
777
if (ret != 0)
778
return ret;
779
780
ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
781
if (ret != 0)
782
goto out_unpin;
783
784
ret = i915_gem_object_put_fence(new_bo);
785
if (ret)
786
goto out_unpin;
787
788
if (!overlay->active) {
789
regs = intel_overlay_map_regs(overlay);
790
if (!regs) {
791
ret = -ENOMEM;
792
goto out_unpin;
793
}
794
regs->OCONFIG = OCONF_CC_OUT_8BIT;
795
if (IS_GEN4(overlay->dev))
796
regs->OCONFIG |= OCONF_CSC_MODE_BT709;
797
regs->OCONFIG |= overlay->crtc->pipe == 0 ?
798
OCONF_PIPE_A : OCONF_PIPE_B;
799
intel_overlay_unmap_regs(overlay, regs);
800
801
ret = intel_overlay_on(overlay);
802
if (ret != 0)
803
goto out_unpin;
804
}
805
806
regs = intel_overlay_map_regs(overlay);
807
if (!regs) {
808
ret = -ENOMEM;
809
goto out_unpin;
810
}
811
812
regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
813
regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
814
815
if (params->format & I915_OVERLAY_YUV_PACKED)
816
tmp_width = packed_width_bytes(params->format, params->src_w);
817
else
818
tmp_width = params->src_w;
819
820
regs->SWIDTH = params->src_w;
821
regs->SWIDTHSW = calc_swidthsw(overlay->dev,
822
params->offset_Y, tmp_width);
823
regs->SHEIGHT = params->src_h;
824
regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y;
825
regs->OSTRIDE = params->stride_Y;
826
827
if (params->format & I915_OVERLAY_YUV_PLANAR) {
828
int uv_hscale = uv_hsubsampling(params->format);
829
int uv_vscale = uv_vsubsampling(params->format);
830
u32 tmp_U, tmp_V;
831
regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
832
tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
833
params->src_w/uv_hscale);
834
tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
835
params->src_w/uv_hscale);
836
regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
837
regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
838
regs->OBUF_0U = new_bo->gtt_offset + params->offset_U;
839
regs->OBUF_0V = new_bo->gtt_offset + params->offset_V;
840
regs->OSTRIDE |= params->stride_UV << 16;
841
}
842
843
scale_changed = update_scaling_factors(overlay, regs, params);
844
845
update_colorkey(overlay, regs);
846
847
regs->OCMD = overlay_cmd_reg(params);
848
849
intel_overlay_unmap_regs(overlay, regs);
850
851
ret = intel_overlay_continue(overlay, scale_changed);
852
if (ret)
853
goto out_unpin;
854
855
overlay->old_vid_bo = overlay->vid_bo;
856
overlay->vid_bo = new_bo;
857
858
return 0;
859
860
out_unpin:
861
i915_gem_object_unpin(new_bo);
862
return ret;
863
}
864
865
int intel_overlay_switch_off(struct intel_overlay *overlay)
866
{
867
struct overlay_registers *regs;
868
struct drm_device *dev = overlay->dev;
869
int ret;
870
871
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
872
BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
873
874
ret = intel_overlay_recover_from_interrupt(overlay);
875
if (ret != 0)
876
return ret;
877
878
if (!overlay->active)
879
return 0;
880
881
ret = intel_overlay_release_old_vid(overlay);
882
if (ret != 0)
883
return ret;
884
885
regs = intel_overlay_map_regs(overlay);
886
regs->OCMD = 0;
887
intel_overlay_unmap_regs(overlay, regs);
888
889
ret = intel_overlay_off(overlay);
890
if (ret != 0)
891
return ret;
892
893
intel_overlay_off_tail(overlay);
894
return 0;
895
}
896
897
static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
898
struct intel_crtc *crtc)
899
{
900
drm_i915_private_t *dev_priv = overlay->dev->dev_private;
901
902
if (!crtc->active)
903
return -EINVAL;
904
905
/* can't use the overlay with double wide pipe */
906
if (INTEL_INFO(overlay->dev)->gen < 4 &&
907
(I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
908
return -EINVAL;
909
910
return 0;
911
}
912
913
static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
914
{
915
struct drm_device *dev = overlay->dev;
916
drm_i915_private_t *dev_priv = dev->dev_private;
917
u32 pfit_control = I915_READ(PFIT_CONTROL);
918
u32 ratio;
919
920
/* XXX: This is not the same logic as in the xorg driver, but more in
921
* line with the intel documentation for the i965
922
*/
923
if (INTEL_INFO(dev)->gen >= 4) {
924
/* on i965 use the PGM reg to read out the autoscaler values */
925
ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
926
} else {
927
if (pfit_control & VERT_AUTO_SCALE)
928
ratio = I915_READ(PFIT_AUTO_RATIOS);
929
else
930
ratio = I915_READ(PFIT_PGM_RATIOS);
931
ratio >>= PFIT_VERT_SCALE_SHIFT;
932
}
933
934
overlay->pfit_vscale_ratio = ratio;
935
}
936
937
static int check_overlay_dst(struct intel_overlay *overlay,
938
struct drm_intel_overlay_put_image *rec)
939
{
940
struct drm_display_mode *mode = &overlay->crtc->base.mode;
941
942
if (rec->dst_x < mode->crtc_hdisplay &&
943
rec->dst_x + rec->dst_width <= mode->crtc_hdisplay &&
944
rec->dst_y < mode->crtc_vdisplay &&
945
rec->dst_y + rec->dst_height <= mode->crtc_vdisplay)
946
return 0;
947
else
948
return -EINVAL;
949
}
950
951
static int check_overlay_scaling(struct put_image_params *rec)
952
{
953
u32 tmp;
954
955
/* downscaling limit is 8.0 */
956
tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
957
if (tmp > 7)
958
return -EINVAL;
959
tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
960
if (tmp > 7)
961
return -EINVAL;
962
963
return 0;
964
}
965
966
static int check_overlay_src(struct drm_device *dev,
967
struct drm_intel_overlay_put_image *rec,
968
struct drm_i915_gem_object *new_bo)
969
{
970
int uv_hscale = uv_hsubsampling(rec->flags);
971
int uv_vscale = uv_vsubsampling(rec->flags);
972
u32 stride_mask;
973
int depth;
974
u32 tmp;
975
976
/* check src dimensions */
977
if (IS_845G(dev) || IS_I830(dev)) {
978
if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
979
rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
980
return -EINVAL;
981
} else {
982
if (rec->src_height > IMAGE_MAX_HEIGHT ||
983
rec->src_width > IMAGE_MAX_WIDTH)
984
return -EINVAL;
985
}
986
987
/* better safe than sorry, use 4 as the maximal subsampling ratio */
988
if (rec->src_height < N_VERT_Y_TAPS*4 ||
989
rec->src_width < N_HORIZ_Y_TAPS*4)
990
return -EINVAL;
991
992
/* check alignment constraints */
993
switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
994
case I915_OVERLAY_RGB:
995
/* not implemented */
996
return -EINVAL;
997
998
case I915_OVERLAY_YUV_PACKED:
999
if (uv_vscale != 1)
1000
return -EINVAL;
1001
1002
depth = packed_depth_bytes(rec->flags);
1003
if (depth < 0)
1004
return depth;
1005
1006
/* ignore UV planes */
1007
rec->stride_UV = 0;
1008
rec->offset_U = 0;
1009
rec->offset_V = 0;
1010
/* check pixel alignment */
1011
if (rec->offset_Y % depth)
1012
return -EINVAL;
1013
break;
1014
1015
case I915_OVERLAY_YUV_PLANAR:
1016
if (uv_vscale < 0 || uv_hscale < 0)
1017
return -EINVAL;
1018
/* no offset restrictions for planar formats */
1019
break;
1020
1021
default:
1022
return -EINVAL;
1023
}
1024
1025
if (rec->src_width % uv_hscale)
1026
return -EINVAL;
1027
1028
/* stride checking */
1029
if (IS_I830(dev) || IS_845G(dev))
1030
stride_mask = 255;
1031
else
1032
stride_mask = 63;
1033
1034
if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
1035
return -EINVAL;
1036
if (IS_GEN4(dev) && rec->stride_Y < 512)
1037
return -EINVAL;
1038
1039
tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
1040
4096 : 8192;
1041
if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
1042
return -EINVAL;
1043
1044
/* check buffer dimensions */
1045
switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1046
case I915_OVERLAY_RGB:
1047
case I915_OVERLAY_YUV_PACKED:
1048
/* always 4 Y values per depth pixels */
1049
if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1050
return -EINVAL;
1051
1052
tmp = rec->stride_Y*rec->src_height;
1053
if (rec->offset_Y + tmp > new_bo->base.size)
1054
return -EINVAL;
1055
break;
1056
1057
case I915_OVERLAY_YUV_PLANAR:
1058
if (rec->src_width > rec->stride_Y)
1059
return -EINVAL;
1060
if (rec->src_width/uv_hscale > rec->stride_UV)
1061
return -EINVAL;
1062
1063
tmp = rec->stride_Y * rec->src_height;
1064
if (rec->offset_Y + tmp > new_bo->base.size)
1065
return -EINVAL;
1066
1067
tmp = rec->stride_UV * (rec->src_height / uv_vscale);
1068
if (rec->offset_U + tmp > new_bo->base.size ||
1069
rec->offset_V + tmp > new_bo->base.size)
1070
return -EINVAL;
1071
break;
1072
}
1073
1074
return 0;
1075
}
1076
1077
/**
1078
* Return the pipe currently connected to the panel fitter,
1079
* or -1 if the panel fitter is not present or not in use
1080
*/
1081
static int intel_panel_fitter_pipe(struct drm_device *dev)
1082
{
1083
struct drm_i915_private *dev_priv = dev->dev_private;
1084
u32 pfit_control;
1085
1086
/* i830 doesn't have a panel fitter */
1087
if (IS_I830(dev))
1088
return -1;
1089
1090
pfit_control = I915_READ(PFIT_CONTROL);
1091
1092
/* See if the panel fitter is in use */
1093
if ((pfit_control & PFIT_ENABLE) == 0)
1094
return -1;
1095
1096
/* 965 can place panel fitter on either pipe */
1097
if (IS_GEN4(dev))
1098
return (pfit_control >> 29) & 0x3;
1099
1100
/* older chips can only use pipe 1 */
1101
return 1;
1102
}
1103
1104
int intel_overlay_put_image(struct drm_device *dev, void *data,
1105
struct drm_file *file_priv)
1106
{
1107
struct drm_intel_overlay_put_image *put_image_rec = data;
1108
drm_i915_private_t *dev_priv = dev->dev_private;
1109
struct intel_overlay *overlay;
1110
struct drm_mode_object *drmmode_obj;
1111
struct intel_crtc *crtc;
1112
struct drm_i915_gem_object *new_bo;
1113
struct put_image_params *params;
1114
int ret;
1115
1116
if (!dev_priv) {
1117
DRM_ERROR("called with no initialization\n");
1118
return -EINVAL;
1119
}
1120
1121
overlay = dev_priv->overlay;
1122
if (!overlay) {
1123
DRM_DEBUG("userspace bug: no overlay\n");
1124
return -ENODEV;
1125
}
1126
1127
if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
1128
mutex_lock(&dev->mode_config.mutex);
1129
mutex_lock(&dev->struct_mutex);
1130
1131
ret = intel_overlay_switch_off(overlay);
1132
1133
mutex_unlock(&dev->struct_mutex);
1134
mutex_unlock(&dev->mode_config.mutex);
1135
1136
return ret;
1137
}
1138
1139
params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
1140
if (!params)
1141
return -ENOMEM;
1142
1143
drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1144
DRM_MODE_OBJECT_CRTC);
1145
if (!drmmode_obj) {
1146
ret = -ENOENT;
1147
goto out_free;
1148
}
1149
crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
1150
1151
new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
1152
put_image_rec->bo_handle));
1153
if (&new_bo->base == NULL) {
1154
ret = -ENOENT;
1155
goto out_free;
1156
}
1157
1158
mutex_lock(&dev->mode_config.mutex);
1159
mutex_lock(&dev->struct_mutex);
1160
1161
if (new_bo->tiling_mode) {
1162
DRM_ERROR("buffer used for overlay image can not be tiled\n");
1163
ret = -EINVAL;
1164
goto out_unlock;
1165
}
1166
1167
ret = intel_overlay_recover_from_interrupt(overlay);
1168
if (ret != 0)
1169
goto out_unlock;
1170
1171
if (overlay->crtc != crtc) {
1172
struct drm_display_mode *mode = &crtc->base.mode;
1173
ret = intel_overlay_switch_off(overlay);
1174
if (ret != 0)
1175
goto out_unlock;
1176
1177
ret = check_overlay_possible_on_crtc(overlay, crtc);
1178
if (ret != 0)
1179
goto out_unlock;
1180
1181
overlay->crtc = crtc;
1182
crtc->overlay = overlay;
1183
1184
/* line too wide, i.e. one-line-mode */
1185
if (mode->hdisplay > 1024 &&
1186
intel_panel_fitter_pipe(dev) == crtc->pipe) {
1187
overlay->pfit_active = 1;
1188
update_pfit_vscale_ratio(overlay);
1189
} else
1190
overlay->pfit_active = 0;
1191
}
1192
1193
ret = check_overlay_dst(overlay, put_image_rec);
1194
if (ret != 0)
1195
goto out_unlock;
1196
1197
if (overlay->pfit_active) {
1198
params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1199
overlay->pfit_vscale_ratio);
1200
/* shifting right rounds downwards, so add 1 */
1201
params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1202
overlay->pfit_vscale_ratio) + 1;
1203
} else {
1204
params->dst_y = put_image_rec->dst_y;
1205
params->dst_h = put_image_rec->dst_height;
1206
}
1207
params->dst_x = put_image_rec->dst_x;
1208
params->dst_w = put_image_rec->dst_width;
1209
1210
params->src_w = put_image_rec->src_width;
1211
params->src_h = put_image_rec->src_height;
1212
params->src_scan_w = put_image_rec->src_scan_width;
1213
params->src_scan_h = put_image_rec->src_scan_height;
1214
if (params->src_scan_h > params->src_h ||
1215
params->src_scan_w > params->src_w) {
1216
ret = -EINVAL;
1217
goto out_unlock;
1218
}
1219
1220
ret = check_overlay_src(dev, put_image_rec, new_bo);
1221
if (ret != 0)
1222
goto out_unlock;
1223
params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
1224
params->stride_Y = put_image_rec->stride_Y;
1225
params->stride_UV = put_image_rec->stride_UV;
1226
params->offset_Y = put_image_rec->offset_Y;
1227
params->offset_U = put_image_rec->offset_U;
1228
params->offset_V = put_image_rec->offset_V;
1229
1230
/* Check scaling after src size to prevent a divide-by-zero. */
1231
ret = check_overlay_scaling(params);
1232
if (ret != 0)
1233
goto out_unlock;
1234
1235
ret = intel_overlay_do_put_image(overlay, new_bo, params);
1236
if (ret != 0)
1237
goto out_unlock;
1238
1239
mutex_unlock(&dev->struct_mutex);
1240
mutex_unlock(&dev->mode_config.mutex);
1241
1242
kfree(params);
1243
1244
return 0;
1245
1246
out_unlock:
1247
mutex_unlock(&dev->struct_mutex);
1248
mutex_unlock(&dev->mode_config.mutex);
1249
drm_gem_object_unreference_unlocked(&new_bo->base);
1250
out_free:
1251
kfree(params);
1252
1253
return ret;
1254
}
1255
1256
static void update_reg_attrs(struct intel_overlay *overlay,
1257
struct overlay_registers *regs)
1258
{
1259
regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
1260
regs->OCLRC1 = overlay->saturation;
1261
}
1262
1263
static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
1264
{
1265
int i;
1266
1267
if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
1268
return false;
1269
1270
for (i = 0; i < 3; i++) {
1271
if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
1272
return false;
1273
}
1274
1275
return true;
1276
}
1277
1278
static bool check_gamma5_errata(u32 gamma5)
1279
{
1280
int i;
1281
1282
for (i = 0; i < 3; i++) {
1283
if (((gamma5 >> i*8) & 0xff) == 0x80)
1284
return false;
1285
}
1286
1287
return true;
1288
}
1289
1290
static int check_gamma(struct drm_intel_overlay_attrs *attrs)
1291
{
1292
if (!check_gamma_bounds(0, attrs->gamma0) ||
1293
!check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1294
!check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1295
!check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1296
!check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1297
!check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1298
!check_gamma_bounds(attrs->gamma5, 0x00ffffff))
1299
return -EINVAL;
1300
1301
if (!check_gamma5_errata(attrs->gamma5))
1302
return -EINVAL;
1303
1304
return 0;
1305
}
1306
1307
int intel_overlay_attrs(struct drm_device *dev, void *data,
1308
struct drm_file *file_priv)
1309
{
1310
struct drm_intel_overlay_attrs *attrs = data;
1311
drm_i915_private_t *dev_priv = dev->dev_private;
1312
struct intel_overlay *overlay;
1313
struct overlay_registers *regs;
1314
int ret;
1315
1316
if (!dev_priv) {
1317
DRM_ERROR("called with no initialization\n");
1318
return -EINVAL;
1319
}
1320
1321
overlay = dev_priv->overlay;
1322
if (!overlay) {
1323
DRM_DEBUG("userspace bug: no overlay\n");
1324
return -ENODEV;
1325
}
1326
1327
mutex_lock(&dev->mode_config.mutex);
1328
mutex_lock(&dev->struct_mutex);
1329
1330
ret = -EINVAL;
1331
if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
1332
attrs->color_key = overlay->color_key;
1333
attrs->brightness = overlay->brightness;
1334
attrs->contrast = overlay->contrast;
1335
attrs->saturation = overlay->saturation;
1336
1337
if (!IS_GEN2(dev)) {
1338
attrs->gamma0 = I915_READ(OGAMC0);
1339
attrs->gamma1 = I915_READ(OGAMC1);
1340
attrs->gamma2 = I915_READ(OGAMC2);
1341
attrs->gamma3 = I915_READ(OGAMC3);
1342
attrs->gamma4 = I915_READ(OGAMC4);
1343
attrs->gamma5 = I915_READ(OGAMC5);
1344
}
1345
} else {
1346
if (attrs->brightness < -128 || attrs->brightness > 127)
1347
goto out_unlock;
1348
if (attrs->contrast > 255)
1349
goto out_unlock;
1350
if (attrs->saturation > 1023)
1351
goto out_unlock;
1352
1353
overlay->color_key = attrs->color_key;
1354
overlay->brightness = attrs->brightness;
1355
overlay->contrast = attrs->contrast;
1356
overlay->saturation = attrs->saturation;
1357
1358
regs = intel_overlay_map_regs(overlay);
1359
if (!regs) {
1360
ret = -ENOMEM;
1361
goto out_unlock;
1362
}
1363
1364
update_reg_attrs(overlay, regs);
1365
1366
intel_overlay_unmap_regs(overlay, regs);
1367
1368
if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1369
if (IS_GEN2(dev))
1370
goto out_unlock;
1371
1372
if (overlay->active) {
1373
ret = -EBUSY;
1374
goto out_unlock;
1375
}
1376
1377
ret = check_gamma(attrs);
1378
if (ret)
1379
goto out_unlock;
1380
1381
I915_WRITE(OGAMC0, attrs->gamma0);
1382
I915_WRITE(OGAMC1, attrs->gamma1);
1383
I915_WRITE(OGAMC2, attrs->gamma2);
1384
I915_WRITE(OGAMC3, attrs->gamma3);
1385
I915_WRITE(OGAMC4, attrs->gamma4);
1386
I915_WRITE(OGAMC5, attrs->gamma5);
1387
}
1388
}
1389
1390
ret = 0;
1391
out_unlock:
1392
mutex_unlock(&dev->struct_mutex);
1393
mutex_unlock(&dev->mode_config.mutex);
1394
1395
return ret;
1396
}
1397
1398
void intel_setup_overlay(struct drm_device *dev)
1399
{
1400
drm_i915_private_t *dev_priv = dev->dev_private;
1401
struct intel_overlay *overlay;
1402
struct drm_i915_gem_object *reg_bo;
1403
struct overlay_registers *regs;
1404
int ret;
1405
1406
if (!HAS_OVERLAY(dev))
1407
return;
1408
1409
overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
1410
if (!overlay)
1411
return;
1412
1413
mutex_lock(&dev->struct_mutex);
1414
if (WARN_ON(dev_priv->overlay))
1415
goto out_free;
1416
1417
overlay->dev = dev;
1418
1419
reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
1420
if (!reg_bo)
1421
goto out_free;
1422
overlay->reg_bo = reg_bo;
1423
1424
if (OVERLAY_NEEDS_PHYSICAL(dev)) {
1425
ret = i915_gem_attach_phys_object(dev, reg_bo,
1426
I915_GEM_PHYS_OVERLAY_REGS,
1427
PAGE_SIZE);
1428
if (ret) {
1429
DRM_ERROR("failed to attach phys overlay regs\n");
1430
goto out_free_bo;
1431
}
1432
overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
1433
} else {
1434
ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
1435
if (ret) {
1436
DRM_ERROR("failed to pin overlay register bo\n");
1437
goto out_free_bo;
1438
}
1439
overlay->flip_addr = reg_bo->gtt_offset;
1440
1441
ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
1442
if (ret) {
1443
DRM_ERROR("failed to move overlay register bo into the GTT\n");
1444
goto out_unpin_bo;
1445
}
1446
}
1447
1448
/* init all values */
1449
overlay->color_key = 0x0101fe;
1450
overlay->brightness = -19;
1451
overlay->contrast = 75;
1452
overlay->saturation = 146;
1453
1454
regs = intel_overlay_map_regs(overlay);
1455
if (!regs)
1456
goto out_unpin_bo;
1457
1458
memset(regs, 0, sizeof(struct overlay_registers));
1459
update_polyphase_filter(regs);
1460
update_reg_attrs(overlay, regs);
1461
1462
intel_overlay_unmap_regs(overlay, regs);
1463
1464
dev_priv->overlay = overlay;
1465
mutex_unlock(&dev->struct_mutex);
1466
DRM_INFO("initialized overlay support\n");
1467
return;
1468
1469
out_unpin_bo:
1470
if (!OVERLAY_NEEDS_PHYSICAL(dev))
1471
i915_gem_object_unpin(reg_bo);
1472
out_free_bo:
1473
drm_gem_object_unreference(&reg_bo->base);
1474
out_free:
1475
mutex_unlock(&dev->struct_mutex);
1476
kfree(overlay);
1477
return;
1478
}
1479
1480
void intel_cleanup_overlay(struct drm_device *dev)
1481
{
1482
drm_i915_private_t *dev_priv = dev->dev_private;
1483
1484
if (!dev_priv->overlay)
1485
return;
1486
1487
/* The bo's should be free'd by the generic code already.
1488
* Furthermore modesetting teardown happens beforehand so the
1489
* hardware should be off already */
1490
BUG_ON(dev_priv->overlay->active);
1491
1492
drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
1493
kfree(dev_priv->overlay);
1494
}
1495
1496
#ifdef CONFIG_DEBUG_FS
1497
#include <linux/seq_file.h>
1498
1499
struct intel_overlay_error_state {
1500
struct overlay_registers regs;
1501
unsigned long base;
1502
u32 dovsta;
1503
u32 isr;
1504
};
1505
1506
static struct overlay_registers *
1507
intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
1508
{
1509
drm_i915_private_t *dev_priv = overlay->dev->dev_private;
1510
struct overlay_registers *regs;
1511
1512
if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1513
regs = overlay->reg_bo->phys_obj->handle->vaddr;
1514
else
1515
regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
1516
overlay->reg_bo->gtt_offset);
1517
1518
return regs;
1519
}
1520
1521
static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
1522
struct overlay_registers *regs)
1523
{
1524
if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1525
io_mapping_unmap_atomic(regs);
1526
}
1527
1528
1529
struct intel_overlay_error_state *
1530
intel_overlay_capture_error_state(struct drm_device *dev)
1531
{
1532
drm_i915_private_t *dev_priv = dev->dev_private;
1533
struct intel_overlay *overlay = dev_priv->overlay;
1534
struct intel_overlay_error_state *error;
1535
struct overlay_registers __iomem *regs;
1536
1537
if (!overlay || !overlay->active)
1538
return NULL;
1539
1540
error = kmalloc(sizeof(*error), GFP_ATOMIC);
1541
if (error == NULL)
1542
return NULL;
1543
1544
error->dovsta = I915_READ(DOVSTA);
1545
error->isr = I915_READ(ISR);
1546
if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1547
error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
1548
else
1549
error->base = (long) overlay->reg_bo->gtt_offset;
1550
1551
regs = intel_overlay_map_regs_atomic(overlay);
1552
if (!regs)
1553
goto err;
1554
1555
memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
1556
intel_overlay_unmap_regs_atomic(overlay, regs);
1557
1558
return error;
1559
1560
err:
1561
kfree(error);
1562
return NULL;
1563
}
1564
1565
void
1566
intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
1567
{
1568
seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
1569
error->dovsta, error->isr);
1570
seq_printf(m, " Register file at 0x%08lx:\n",
1571
error->base);
1572
1573
#define P(x) seq_printf(m, " " #x ": 0x%08x\n", error->regs.x)
1574
P(OBUF_0Y);
1575
P(OBUF_1Y);
1576
P(OBUF_0U);
1577
P(OBUF_0V);
1578
P(OBUF_1U);
1579
P(OBUF_1V);
1580
P(OSTRIDE);
1581
P(YRGB_VPH);
1582
P(UV_VPH);
1583
P(HORZ_PH);
1584
P(INIT_PHS);
1585
P(DWINPOS);
1586
P(DWINSZ);
1587
P(SWIDTH);
1588
P(SWIDTHSW);
1589
P(SHEIGHT);
1590
P(YRGBSCALE);
1591
P(UVSCALE);
1592
P(OCLRC0);
1593
P(OCLRC1);
1594
P(DCLRKV);
1595
P(DCLRKM);
1596
P(SCLRKVH);
1597
P(SCLRKVL);
1598
P(SCLRKEN);
1599
P(OCONFIG);
1600
P(OCMD);
1601
P(OSTART_0Y);
1602
P(OSTART_1Y);
1603
P(OSTART_0U);
1604
P(OSTART_0V);
1605
P(OSTART_1U);
1606
P(OSTART_1V);
1607
P(OTILEOFF_0Y);
1608
P(OTILEOFF_1Y);
1609
P(OTILEOFF_0U);
1610
P(OTILEOFF_0V);
1611
P(OTILEOFF_1U);
1612
P(OTILEOFF_1V);
1613
P(FASTHSCALE);
1614
P(UVSCALEV);
1615
#undef P
1616
}
1617
#endif
1618
1619