Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/ivtv/ivtv-yuv.c
17900 views
1
/*
2
yuv support
3
4
Copyright (C) 2007 Ian Armstrong <[email protected]>
5
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
15
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*/
20
21
#include "ivtv-driver.h"
22
#include "ivtv-udma.h"
23
#include "ivtv-yuv.h"
24
25
/* YUV buffer offsets */
26
const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
27
0x001a8600,
28
0x00240400,
29
0x002d8200,
30
0x00370000,
31
0x00029000,
32
0x000C0E00,
33
0x006B0400,
34
0x00748200
35
};
36
37
static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
38
struct ivtv_dma_frame *args)
39
{
40
struct ivtv_dma_page_info y_dma;
41
struct ivtv_dma_page_info uv_dma;
42
struct yuv_playback_info *yi = &itv->yuv_info;
43
u8 frame = yi->draw_frame;
44
struct yuv_frame_info *f = &yi->new_frame_info[frame];
45
int i;
46
int y_pages, uv_pages;
47
unsigned long y_buffer_offset, uv_buffer_offset;
48
int y_decode_height, uv_decode_height, y_size;
49
50
y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
51
uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
52
53
y_decode_height = uv_decode_height = f->src_h + f->src_y;
54
55
if (f->offset_y)
56
y_buffer_offset += 720 * 16;
57
58
if (y_decode_height & 15)
59
y_decode_height = (y_decode_height + 16) & ~15;
60
61
if (uv_decode_height & 31)
62
uv_decode_height = (uv_decode_height + 32) & ~31;
63
64
y_size = 720 * y_decode_height;
65
66
/* Still in USE */
67
if (dma->SG_length || dma->page_count) {
68
IVTV_DEBUG_WARN
69
("prep_user_dma: SG_length %d page_count %d still full?\n",
70
dma->SG_length, dma->page_count);
71
return -EBUSY;
72
}
73
74
ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height);
75
ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
76
77
/* Get user pages for DMA Xfer */
78
down_read(&current->mm->mmap_sem);
79
y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
80
uv_pages = 0; /* silence gcc. value is set and consumed only if: */
81
if (y_pages == y_dma.page_count) {
82
uv_pages = get_user_pages(current, current->mm,
83
uv_dma.uaddr, uv_dma.page_count, 0, 1,
84
&dma->map[y_pages], NULL);
85
}
86
up_read(&current->mm->mmap_sem);
87
88
if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
89
int rc = -EFAULT;
90
91
if (y_pages == y_dma.page_count) {
92
IVTV_DEBUG_WARN
93
("failed to map uv user pages, returned %d "
94
"expecting %d\n", uv_pages, uv_dma.page_count);
95
96
if (uv_pages >= 0) {
97
for (i = 0; i < uv_pages; i++)
98
put_page(dma->map[y_pages + i]);
99
rc = -EFAULT;
100
} else {
101
rc = uv_pages;
102
}
103
} else {
104
IVTV_DEBUG_WARN
105
("failed to map y user pages, returned %d "
106
"expecting %d\n", y_pages, y_dma.page_count);
107
}
108
if (y_pages >= 0) {
109
for (i = 0; i < y_pages; i++)
110
put_page(dma->map[i]);
111
/*
112
* Inherit the -EFAULT from rc's
113
* initialization, but allow it to be
114
* overriden by uv_pages above if it was an
115
* actual errno.
116
*/
117
} else {
118
rc = y_pages;
119
}
120
return rc;
121
}
122
123
dma->page_count = y_pages + uv_pages;
124
125
/* Fill & map SG List */
126
if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
127
IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
128
for (i = 0; i < dma->page_count; i++) {
129
put_page(dma->map[i]);
130
}
131
dma->page_count = 0;
132
return -ENOMEM;
133
}
134
dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
135
136
/* Fill SG Array with new values */
137
ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
138
139
/* If we've offset the y plane, ensure top area is blanked */
140
if (f->offset_y && yi->blanking_dmaptr) {
141
dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
142
dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr);
143
dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
144
dma->SG_length++;
145
}
146
147
/* Tag SG Array with Interrupt Bit */
148
dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
149
150
ivtv_udma_sync_for_device(itv);
151
return 0;
152
}
153
154
/* We rely on a table held in the firmware - Quick check. */
155
int ivtv_yuv_filter_check(struct ivtv *itv)
156
{
157
int i, y, uv;
158
159
for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) {
160
if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) ||
161
(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) {
162
IVTV_WARN ("YUV filter table not found in firmware.\n");
163
return -1;
164
}
165
}
166
return 0;
167
}
168
169
static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
170
{
171
u32 i, line;
172
173
/* If any filter is -1, then don't update it */
174
if (h_filter > -1) {
175
if (h_filter > 4)
176
h_filter = 4;
177
i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384);
178
for (line = 0; line < 16; line++) {
179
write_reg(read_dec(i), 0x02804);
180
write_reg(read_dec(i), 0x0281c);
181
i += 4;
182
write_reg(read_dec(i), 0x02808);
183
write_reg(read_dec(i), 0x02820);
184
i += 4;
185
write_reg(read_dec(i), 0x0280c);
186
write_reg(read_dec(i), 0x02824);
187
i += 4;
188
write_reg(read_dec(i), 0x02810);
189
write_reg(read_dec(i), 0x02828);
190
i += 4;
191
write_reg(read_dec(i), 0x02814);
192
write_reg(read_dec(i), 0x0282c);
193
i += 8;
194
write_reg(0, 0x02818);
195
write_reg(0, 0x02830);
196
}
197
IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter);
198
}
199
200
if (v_filter_1 > -1) {
201
if (v_filter_1 > 4)
202
v_filter_1 = 4;
203
i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192);
204
for (line = 0; line < 16; line++) {
205
write_reg(read_dec(i), 0x02900);
206
i += 4;
207
write_reg(read_dec(i), 0x02904);
208
i += 8;
209
write_reg(0, 0x02908);
210
}
211
IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1);
212
}
213
214
if (v_filter_2 > -1) {
215
if (v_filter_2 > 4)
216
v_filter_2 = 4;
217
i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192);
218
for (line = 0; line < 16; line++) {
219
write_reg(read_dec(i), 0x0290c);
220
i += 4;
221
write_reg(read_dec(i), 0x02910);
222
i += 8;
223
write_reg(0, 0x02914);
224
}
225
IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2);
226
}
227
}
228
229
static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f)
230
{
231
struct yuv_playback_info *yi = &itv->yuv_info;
232
u32 reg_2834, reg_2838, reg_283c;
233
u32 reg_2844, reg_2854, reg_285c;
234
u32 reg_2864, reg_2874, reg_2890;
235
u32 reg_2870, reg_2870_base, reg_2870_offset;
236
int x_cutoff;
237
int h_filter;
238
u32 master_width;
239
240
IVTV_DEBUG_WARN
241
("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
242
f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x);
243
244
/* How wide is the src image */
245
x_cutoff = f->src_w + f->src_x;
246
247
/* Set the display width */
248
reg_2834 = f->dst_w;
249
reg_2838 = reg_2834;
250
251
/* Set the display position */
252
reg_2890 = f->dst_x;
253
254
/* Index into the image horizontally */
255
reg_2870 = 0;
256
257
/* 2870 is normally fudged to align video coords with osd coords.
258
If running full screen, it causes an unwanted left shift
259
Remove the fudge if we almost fill the screen.
260
Gradually adjust the offset to avoid the video 'snapping'
261
left/right if it gets dragged through this region.
262
Only do this if osd is full width. */
263
if (f->vis_w == 720) {
264
if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680))
265
reg_2870 = 10 - (f->tru_x - f->pan_x) / 4;
266
else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660))
267
reg_2870 = (10 + (f->tru_x - f->pan_x) / 2);
268
269
if (f->dst_w >= f->src_w)
270
reg_2870 = reg_2870 << 16 | reg_2870;
271
else
272
reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
273
}
274
275
if (f->dst_w < f->src_w)
276
reg_2870 = 0x000d000e - reg_2870;
277
else
278
reg_2870 = 0x0012000e - reg_2870;
279
280
/* We're also using 2870 to shift the image left (src_x & negative dst_x) */
281
reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19;
282
283
if (f->dst_w >= f->src_w) {
284
x_cutoff &= ~1;
285
master_width = (f->src_w * 0x00200000) / (f->dst_w);
286
if (master_width * f->dst_w != f->src_w * 0x00200000)
287
master_width++;
288
reg_2834 = (reg_2834 << 16) | x_cutoff;
289
reg_2838 = (reg_2838 << 16) | x_cutoff;
290
reg_283c = master_width >> 2;
291
reg_2844 = master_width >> 2;
292
reg_2854 = master_width;
293
reg_285c = master_width >> 1;
294
reg_2864 = master_width >> 1;
295
296
/* We also need to factor in the scaling
297
(src_w - dst_w) / (src_w / 4) */
298
if (f->dst_w > f->src_w)
299
reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14);
300
else
301
reg_2870_base = 0;
302
303
reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
304
reg_2874 = 0;
305
} else if (f->dst_w < f->src_w / 2) {
306
master_width = (f->src_w * 0x00080000) / f->dst_w;
307
if (master_width * f->dst_w != f->src_w * 0x00080000)
308
master_width++;
309
reg_2834 = (reg_2834 << 16) | x_cutoff;
310
reg_2838 = (reg_2838 << 16) | x_cutoff;
311
reg_283c = master_width >> 2;
312
reg_2844 = master_width >> 1;
313
reg_2854 = master_width;
314
reg_285c = master_width >> 1;
315
reg_2864 = master_width >> 1;
316
reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset;
317
reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16;
318
reg_2874 = 0x00000012;
319
} else {
320
master_width = (f->src_w * 0x00100000) / f->dst_w;
321
if (master_width * f->dst_w != f->src_w * 0x00100000)
322
master_width++;
323
reg_2834 = (reg_2834 << 16) | x_cutoff;
324
reg_2838 = (reg_2838 << 16) | x_cutoff;
325
reg_283c = master_width >> 2;
326
reg_2844 = master_width >> 1;
327
reg_2854 = master_width;
328
reg_285c = master_width >> 1;
329
reg_2864 = master_width >> 1;
330
reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1;
331
reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16;
332
reg_2874 = 0x00000001;
333
}
334
335
/* Select the horizontal filter */
336
if (f->src_w == f->dst_w) {
337
/* An exact size match uses filter 0 */
338
h_filter = 0;
339
} else {
340
/* Figure out which filter to use */
341
h_filter = ((f->src_w << 16) / f->dst_w) >> 15;
342
h_filter = (h_filter >> 1) + (h_filter & 1);
343
/* Only an exact size match can use filter 0 */
344
h_filter += !h_filter;
345
}
346
347
write_reg(reg_2834, 0x02834);
348
write_reg(reg_2838, 0x02838);
349
IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
350
yi->reg_2834, reg_2834, yi->reg_2838, reg_2838);
351
352
write_reg(reg_283c, 0x0283c);
353
write_reg(reg_2844, 0x02844);
354
355
IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
356
yi->reg_283c, reg_283c, yi->reg_2844, reg_2844);
357
358
write_reg(0x00080514, 0x02840);
359
write_reg(0x00100514, 0x02848);
360
IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
361
yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514);
362
363
write_reg(reg_2854, 0x02854);
364
IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
365
yi->reg_2854, reg_2854);
366
367
write_reg(reg_285c, 0x0285c);
368
write_reg(reg_2864, 0x02864);
369
IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
370
yi->reg_285c, reg_285c, yi->reg_2864, reg_2864);
371
372
write_reg(reg_2874, 0x02874);
373
IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
374
yi->reg_2874, reg_2874);
375
376
write_reg(reg_2870, 0x02870);
377
IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
378
yi->reg_2870, reg_2870);
379
380
write_reg(reg_2890, 0x02890);
381
IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
382
yi->reg_2890, reg_2890);
383
384
/* Only update the filter if we really need to */
385
if (h_filter != yi->h_filter) {
386
ivtv_yuv_filter(itv, h_filter, -1, -1);
387
yi->h_filter = h_filter;
388
}
389
}
390
391
static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f)
392
{
393
struct yuv_playback_info *yi = &itv->yuv_info;
394
u32 master_height;
395
u32 reg_2918, reg_291c, reg_2920, reg_2928;
396
u32 reg_2930, reg_2934, reg_293c;
397
u32 reg_2940, reg_2944, reg_294c;
398
u32 reg_2950, reg_2954, reg_2958, reg_295c;
399
u32 reg_2960, reg_2964, reg_2968, reg_296c;
400
u32 reg_289c;
401
u32 src_major_y, src_minor_y;
402
u32 src_major_uv, src_minor_uv;
403
u32 reg_2964_base, reg_2968_base;
404
int v_filter_1, v_filter_2;
405
406
IVTV_DEBUG_WARN
407
("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
408
f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y);
409
410
/* What scaling mode is being used... */
411
IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
412
f->interlaced_y ? "Interlaced" : "Progressive");
413
414
IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
415
f->interlaced_uv ? "Interlaced" : "Progressive");
416
417
/* What is the source video being treated as... */
418
IVTV_DEBUG_WARN("Source video: %s\n",
419
f->interlaced ? "Interlaced" : "Progressive");
420
421
/* We offset into the image using two different index methods, so split
422
the y source coord into two parts. */
423
if (f->src_y < 8) {
424
src_minor_uv = f->src_y;
425
src_major_uv = 0;
426
} else {
427
src_minor_uv = 8;
428
src_major_uv = f->src_y - 8;
429
}
430
431
src_minor_y = src_minor_uv;
432
src_major_y = src_major_uv;
433
434
if (f->offset_y)
435
src_minor_y += 16;
436
437
if (f->interlaced_y)
438
reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y);
439
else
440
reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1);
441
442
if (f->interlaced_uv)
443
reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1);
444
else
445
reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv);
446
447
reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14;
448
reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14;
449
450
if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) {
451
master_height = (f->src_h * 0x00400000) / f->dst_h;
452
if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2)
453
master_height++;
454
reg_2920 = master_height >> 2;
455
reg_2928 = master_height >> 3;
456
reg_2930 = master_height;
457
reg_2940 = master_height >> 1;
458
reg_2964_base >>= 3;
459
reg_2968_base >>= 3;
460
reg_296c = 0x00000000;
461
} else if (f->dst_h >= f->src_h) {
462
master_height = (f->src_h * 0x00400000) / f->dst_h;
463
master_height = (master_height >> 1) + (master_height & 1);
464
reg_2920 = master_height >> 2;
465
reg_2928 = master_height >> 2;
466
reg_2930 = master_height;
467
reg_2940 = master_height >> 1;
468
reg_296c = 0x00000000;
469
if (f->interlaced_y) {
470
reg_2964_base >>= 3;
471
} else {
472
reg_296c++;
473
reg_2964_base >>= 2;
474
}
475
if (f->interlaced_uv)
476
reg_2928 >>= 1;
477
reg_2968_base >>= 3;
478
} else if (f->dst_h >= f->src_h / 2) {
479
master_height = (f->src_h * 0x00200000) / f->dst_h;
480
master_height = (master_height >> 1) + (master_height & 1);
481
reg_2920 = master_height >> 2;
482
reg_2928 = master_height >> 2;
483
reg_2930 = master_height;
484
reg_2940 = master_height;
485
reg_296c = 0x00000101;
486
if (f->interlaced_y) {
487
reg_2964_base >>= 2;
488
} else {
489
reg_296c++;
490
reg_2964_base >>= 1;
491
}
492
if (f->interlaced_uv)
493
reg_2928 >>= 1;
494
reg_2968_base >>= 2;
495
} else {
496
master_height = (f->src_h * 0x00100000) / f->dst_h;
497
master_height = (master_height >> 1) + (master_height & 1);
498
reg_2920 = master_height >> 2;
499
reg_2928 = master_height >> 2;
500
reg_2930 = master_height;
501
reg_2940 = master_height;
502
reg_2964_base >>= 1;
503
reg_2968_base >>= 2;
504
reg_296c = 0x00000102;
505
}
506
507
/* FIXME These registers change depending on scaled / unscaled output
508
We really need to work out what they should be */
509
if (f->src_h == f->dst_h) {
510
reg_2934 = 0x00020000;
511
reg_293c = 0x00100000;
512
reg_2944 = 0x00040000;
513
reg_294c = 0x000b0000;
514
} else {
515
reg_2934 = 0x00000FF0;
516
reg_293c = 0x00000FF0;
517
reg_2944 = 0x00000FF0;
518
reg_294c = 0x00000FF0;
519
}
520
521
/* The first line to be displayed */
522
reg_2950 = 0x00010000 + src_major_y;
523
if (f->interlaced_y)
524
reg_2950 += 0x00010000;
525
reg_2954 = reg_2950 + 1;
526
527
reg_2958 = 0x00010000 + (src_major_y >> 1);
528
if (f->interlaced_uv)
529
reg_2958 += 0x00010000;
530
reg_295c = reg_2958 + 1;
531
532
if (yi->decode_height == 480)
533
reg_289c = 0x011e0017;
534
else
535
reg_289c = 0x01500017;
536
537
if (f->dst_y < 0)
538
reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);
539
else
540
reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1);
541
542
/* How much of the source to decode.
543
Take into account the source offset */
544
reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) |
545
(((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15);
546
547
/* Calculate correct value for register 2964 */
548
if (f->src_h == f->dst_h) {
549
reg_2964 = 1;
550
} else {
551
reg_2964 = 2 + ((f->dst_h << 1) / f->src_h);
552
reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);
553
}
554
reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);
555
reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
556
557
/* Okay, we've wasted time working out the correct value,
558
but if we use it, it fouls the the window alignment.
559
Fudge it to what we want... */
560
reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
561
reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
562
563
/* Deviate further from what it should be. I find the flicker headache
564
inducing so try to reduce it slightly. Leave 2968 as-is otherwise
565
colours foul. */
566
if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h))
567
reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2);
568
569
if (!f->interlaced_y)
570
reg_2964 -= 0x00010001;
571
if (!f->interlaced_uv)
572
reg_2968 -= 0x00010001;
573
574
reg_2964 += ((reg_2964_base << 16) | reg_2964_base);
575
reg_2968 += ((reg_2968_base << 16) | reg_2968_base);
576
577
/* Select the vertical filter */
578
if (f->src_h == f->dst_h) {
579
/* An exact size match uses filter 0/1 */
580
v_filter_1 = 0;
581
v_filter_2 = 1;
582
} else {
583
/* Figure out which filter to use */
584
v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15;
585
v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
586
/* Only an exact size match can use filter 0 */
587
v_filter_1 += !v_filter_1;
588
v_filter_2 = v_filter_1;
589
}
590
591
write_reg(reg_2934, 0x02934);
592
write_reg(reg_293c, 0x0293c);
593
IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
594
yi->reg_2934, reg_2934, yi->reg_293c, reg_293c);
595
write_reg(reg_2944, 0x02944);
596
write_reg(reg_294c, 0x0294c);
597
IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
598
yi->reg_2944, reg_2944, yi->reg_294c, reg_294c);
599
600
/* Ensure 2970 is 0 (does it ever change ?) */
601
/* write_reg(0,0x02970); */
602
/* IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */
603
604
write_reg(reg_2930, 0x02938);
605
write_reg(reg_2930, 0x02930);
606
IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
607
yi->reg_2930, reg_2930, yi->reg_2938, reg_2930);
608
609
write_reg(reg_2928, 0x02928);
610
write_reg(reg_2928 + 0x514, 0x0292C);
611
IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
612
yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514);
613
614
write_reg(reg_2920, 0x02920);
615
write_reg(reg_2920 + 0x514, 0x02924);
616
IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
617
yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514);
618
619
write_reg(reg_2918, 0x02918);
620
write_reg(reg_291c, 0x0291C);
621
IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
622
yi->reg_2918, reg_2918, yi->reg_291c, reg_291c);
623
624
write_reg(reg_296c, 0x0296c);
625
IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
626
yi->reg_296c, reg_296c);
627
628
write_reg(reg_2940, 0x02948);
629
write_reg(reg_2940, 0x02940);
630
IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
631
yi->reg_2940, reg_2940, yi->reg_2948, reg_2940);
632
633
write_reg(reg_2950, 0x02950);
634
write_reg(reg_2954, 0x02954);
635
IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
636
yi->reg_2950, reg_2950, yi->reg_2954, reg_2954);
637
638
write_reg(reg_2958, 0x02958);
639
write_reg(reg_295c, 0x0295C);
640
IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
641
yi->reg_2958, reg_2958, yi->reg_295c, reg_295c);
642
643
write_reg(reg_2960, 0x02960);
644
IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
645
yi->reg_2960, reg_2960);
646
647
write_reg(reg_2964, 0x02964);
648
write_reg(reg_2968, 0x02968);
649
IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
650
yi->reg_2964, reg_2964, yi->reg_2968, reg_2968);
651
652
write_reg(reg_289c, 0x0289c);
653
IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
654
yi->reg_289c, reg_289c);
655
656
/* Only update filter 1 if we really need to */
657
if (v_filter_1 != yi->v_filter_1) {
658
ivtv_yuv_filter(itv, -1, v_filter_1, -1);
659
yi->v_filter_1 = v_filter_1;
660
}
661
662
/* Only update filter 2 if we really need to */
663
if (v_filter_2 != yi->v_filter_2) {
664
ivtv_yuv_filter(itv, -1, -1, v_filter_2);
665
yi->v_filter_2 = v_filter_2;
666
}
667
}
668
669
/* Modify the supplied coordinate information to fit the visible osd area */
670
static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
671
{
672
struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;
673
int osd_crop;
674
u32 osd_scale;
675
u32 yuv_update = 0;
676
677
/* Sorry, but no negative coords for src */
678
if (f->src_x < 0)
679
f->src_x = 0;
680
if (f->src_y < 0)
681
f->src_y = 0;
682
683
/* Can only reduce width down to 1/4 original size */
684
if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {
685
f->src_x += osd_crop / 2;
686
f->src_w = (f->src_w - osd_crop) & ~3;
687
f->dst_w = f->src_w / 4;
688
f->dst_w += f->dst_w & 1;
689
}
690
691
/* Can only reduce height down to 1/4 original size */
692
if (f->src_h / f->dst_h >= 2) {
693
/* Overflow may be because we're running progressive,
694
so force mode switch */
695
f->interlaced_y = 1;
696
/* Make sure we're still within limits for interlace */
697
if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {
698
/* If we reach here we'll have to force the height. */
699
f->src_y += osd_crop / 2;
700
f->src_h = (f->src_h - osd_crop) & ~3;
701
f->dst_h = f->src_h / 4;
702
f->dst_h += f->dst_h & 1;
703
}
704
}
705
706
/* If there's nothing to safe to display, we may as well stop now */
707
if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
708
(int)f->src_w <= 2 || (int)f->src_h <= 2) {
709
return IVTV_YUV_UPDATE_INVALID;
710
}
711
712
/* Ensure video remains inside OSD area */
713
osd_scale = (f->src_h << 16) / f->dst_h;
714
715
if ((osd_crop = f->pan_y - f->dst_y) > 0) {
716
/* Falls off the upper edge - crop */
717
f->src_y += (osd_scale * osd_crop) >> 16;
718
f->src_h -= (osd_scale * osd_crop) >> 16;
719
f->dst_h -= osd_crop;
720
f->dst_y = 0;
721
} else {
722
f->dst_y -= f->pan_y;
723
}
724
725
if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {
726
/* Falls off the lower edge - crop */
727
f->dst_h -= osd_crop;
728
f->src_h -= (osd_scale * osd_crop) >> 16;
729
}
730
731
osd_scale = (f->src_w << 16) / f->dst_w;
732
733
if ((osd_crop = f->pan_x - f->dst_x) > 0) {
734
/* Fall off the left edge - crop */
735
f->src_x += (osd_scale * osd_crop) >> 16;
736
f->src_w -= (osd_scale * osd_crop) >> 16;
737
f->dst_w -= osd_crop;
738
f->dst_x = 0;
739
} else {
740
f->dst_x -= f->pan_x;
741
}
742
743
if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {
744
/* Falls off the right edge - crop */
745
f->dst_w -= osd_crop;
746
f->src_w -= (osd_scale * osd_crop) >> 16;
747
}
748
749
if (itv->yuv_info.track_osd) {
750
/* The OSD can be moved. Track to it */
751
f->dst_x += itv->yuv_info.osd_x_offset;
752
f->dst_y += itv->yuv_info.osd_y_offset;
753
}
754
755
/* Width & height for both src & dst must be even.
756
Same for coordinates. */
757
f->dst_w &= ~1;
758
f->dst_x &= ~1;
759
760
f->src_w += f->src_x & 1;
761
f->src_x &= ~1;
762
763
f->src_w &= ~1;
764
f->dst_w &= ~1;
765
766
f->dst_h &= ~1;
767
f->dst_y &= ~1;
768
769
f->src_h += f->src_y & 1;
770
f->src_y &= ~1;
771
772
f->src_h &= ~1;
773
f->dst_h &= ~1;
774
775
/* Due to rounding, we may have reduced the output size to <1/4 of
776
the source. Check again, but this time just resize. Don't change
777
source coordinates */
778
if (f->dst_w < f->src_w / 4) {
779
f->src_w &= ~3;
780
f->dst_w = f->src_w / 4;
781
f->dst_w += f->dst_w & 1;
782
}
783
if (f->dst_h < f->src_h / 4) {
784
f->src_h &= ~3;
785
f->dst_h = f->src_h / 4;
786
f->dst_h += f->dst_h & 1;
787
}
788
789
/* Check again. If there's nothing to safe to display, stop now */
790
if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
791
(int)f->src_w <= 2 || (int)f->src_h <= 2) {
792
return IVTV_YUV_UPDATE_INVALID;
793
}
794
795
/* Both x offset & width are linked, so they have to be done together */
796
if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
797
(of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
798
(of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
799
yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
800
}
801
802
if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
803
(of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
804
(of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
805
(of->lace_mode != f->lace_mode) ||
806
(of->interlaced_y != f->interlaced_y) ||
807
(of->interlaced_uv != f->interlaced_uv)) {
808
yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
809
}
810
811
return yuv_update;
812
}
813
814
/* Update the scaling register to the requested value */
815
void ivtv_yuv_work_handler(struct ivtv *itv)
816
{
817
struct yuv_playback_info *yi = &itv->yuv_info;
818
struct yuv_frame_info f;
819
int frame = yi->update_frame;
820
u32 yuv_update;
821
822
IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
823
f = yi->new_frame_info[frame];
824
825
if (yi->track_osd) {
826
/* Snapshot the osd pan info */
827
f.pan_x = yi->osd_x_pan;
828
f.pan_y = yi->osd_y_pan;
829
f.vis_w = yi->osd_vis_w;
830
f.vis_h = yi->osd_vis_h;
831
} else {
832
/* Not tracking the osd, so assume full screen */
833
f.pan_x = 0;
834
f.pan_y = 0;
835
f.vis_w = 720;
836
f.vis_h = yi->decode_height;
837
}
838
839
/* Calculate the display window coordinates. Exit if nothing left */
840
if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
841
return;
842
843
if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
844
write_reg(0x01008080, 0x2898);
845
} else if (yuv_update) {
846
write_reg(0x00108080, 0x2898);
847
848
if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
849
ivtv_yuv_handle_horizontal(itv, &f);
850
851
if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
852
ivtv_yuv_handle_vertical(itv, &f);
853
}
854
yi->old_frame_info = f;
855
}
856
857
static void ivtv_yuv_init(struct ivtv *itv)
858
{
859
struct yuv_playback_info *yi = &itv->yuv_info;
860
861
IVTV_DEBUG_YUV("ivtv_yuv_init\n");
862
863
/* Take a snapshot of the current register settings */
864
yi->reg_2834 = read_reg(0x02834);
865
yi->reg_2838 = read_reg(0x02838);
866
yi->reg_283c = read_reg(0x0283c);
867
yi->reg_2840 = read_reg(0x02840);
868
yi->reg_2844 = read_reg(0x02844);
869
yi->reg_2848 = read_reg(0x02848);
870
yi->reg_2854 = read_reg(0x02854);
871
yi->reg_285c = read_reg(0x0285c);
872
yi->reg_2864 = read_reg(0x02864);
873
yi->reg_2870 = read_reg(0x02870);
874
yi->reg_2874 = read_reg(0x02874);
875
yi->reg_2898 = read_reg(0x02898);
876
yi->reg_2890 = read_reg(0x02890);
877
878
yi->reg_289c = read_reg(0x0289c);
879
yi->reg_2918 = read_reg(0x02918);
880
yi->reg_291c = read_reg(0x0291c);
881
yi->reg_2920 = read_reg(0x02920);
882
yi->reg_2924 = read_reg(0x02924);
883
yi->reg_2928 = read_reg(0x02928);
884
yi->reg_292c = read_reg(0x0292c);
885
yi->reg_2930 = read_reg(0x02930);
886
yi->reg_2934 = read_reg(0x02934);
887
yi->reg_2938 = read_reg(0x02938);
888
yi->reg_293c = read_reg(0x0293c);
889
yi->reg_2940 = read_reg(0x02940);
890
yi->reg_2944 = read_reg(0x02944);
891
yi->reg_2948 = read_reg(0x02948);
892
yi->reg_294c = read_reg(0x0294c);
893
yi->reg_2950 = read_reg(0x02950);
894
yi->reg_2954 = read_reg(0x02954);
895
yi->reg_2958 = read_reg(0x02958);
896
yi->reg_295c = read_reg(0x0295c);
897
yi->reg_2960 = read_reg(0x02960);
898
yi->reg_2964 = read_reg(0x02964);
899
yi->reg_2968 = read_reg(0x02968);
900
yi->reg_296c = read_reg(0x0296c);
901
yi->reg_2970 = read_reg(0x02970);
902
903
yi->v_filter_1 = -1;
904
yi->v_filter_2 = -1;
905
yi->h_filter = -1;
906
907
/* Set some valid size info */
908
yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
909
yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
910
911
/* Bit 2 of reg 2878 indicates current decoder output format
912
0 : NTSC 1 : PAL */
913
if (read_reg(0x2878) & 4)
914
yi->decode_height = 576;
915
else
916
yi->decode_height = 480;
917
918
if (!itv->osd_info) {
919
yi->osd_vis_w = 720 - yi->osd_x_offset;
920
yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
921
} else {
922
/* If no visible size set, assume full size */
923
if (!yi->osd_vis_w)
924
yi->osd_vis_w = 720 - yi->osd_x_offset;
925
926
if (!yi->osd_vis_h) {
927
yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
928
} else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
929
/* If output video standard has changed, requested height may
930
not be legal */
931
IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
932
yi->osd_vis_h + yi->osd_y_offset,
933
yi->decode_height);
934
yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
935
}
936
}
937
938
/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
939
yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
940
if (yi->blanking_ptr) {
941
yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
942
} else {
943
yi->blanking_dmaptr = 0;
944
IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
945
}
946
947
/* Enable YUV decoder output */
948
write_reg_sync(0x01, IVTV_REG_VDM);
949
950
set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
951
atomic_set(&yi->next_dma_frame, 0);
952
}
953
954
/* Get next available yuv buffer on PVR350 */
955
static void ivtv_yuv_next_free(struct ivtv *itv)
956
{
957
int draw, display;
958
struct yuv_playback_info *yi = &itv->yuv_info;
959
960
if (atomic_read(&yi->next_dma_frame) == -1)
961
ivtv_yuv_init(itv);
962
963
draw = atomic_read(&yi->next_fill_frame);
964
display = atomic_read(&yi->next_dma_frame);
965
966
if (display > draw)
967
display -= IVTV_YUV_BUFFERS;
968
969
if (draw - display >= yi->max_frames_buffered)
970
draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
971
else
972
yi->new_frame_info[draw].update = 0;
973
974
yi->draw_frame = draw;
975
}
976
977
/* Set up frame according to ivtv_dma_frame parameters */
978
static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
979
{
980
struct yuv_playback_info *yi = &itv->yuv_info;
981
u8 frame = yi->draw_frame;
982
u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
983
struct yuv_frame_info *nf = &yi->new_frame_info[frame];
984
struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
985
int lace_threshold = yi->lace_threshold;
986
987
/* Preserve old update flag in case we're overwriting a queued frame */
988
int update = nf->update;
989
990
/* Take a snapshot of the yuv coordinate information */
991
nf->src_x = args->src.left;
992
nf->src_y = args->src.top;
993
nf->src_w = args->src.width;
994
nf->src_h = args->src.height;
995
nf->dst_x = args->dst.left;
996
nf->dst_y = args->dst.top;
997
nf->dst_w = args->dst.width;
998
nf->dst_h = args->dst.height;
999
nf->tru_x = args->dst.left;
1000
nf->tru_w = args->src_width;
1001
nf->tru_h = args->src_height;
1002
1003
/* Are we going to offset the Y plane */
1004
nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
1005
1006
nf->update = 0;
1007
nf->interlaced_y = 0;
1008
nf->interlaced_uv = 0;
1009
nf->delay = 0;
1010
nf->sync_field = 0;
1011
nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
1012
1013
if (lace_threshold < 0)
1014
lace_threshold = yi->decode_height - 1;
1015
1016
/* Work out the lace settings */
1017
switch (nf->lace_mode) {
1018
case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
1019
nf->interlaced = 0;
1020
if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
1021
nf->interlaced_y = 0;
1022
else
1023
nf->interlaced_y = 1;
1024
1025
if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1026
nf->interlaced_uv = 0;
1027
else
1028
nf->interlaced_uv = 1;
1029
break;
1030
1031
case IVTV_YUV_MODE_AUTO:
1032
if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
1033
nf->interlaced = 0;
1034
if ((nf->tru_h < 512) ||
1035
(nf->tru_h > 576 && nf->tru_h < 1021) ||
1036
(nf->tru_w > 720 && nf->tru_h < 1021))
1037
nf->interlaced_y = 0;
1038
else
1039
nf->interlaced_y = 1;
1040
if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1041
nf->interlaced_uv = 0;
1042
else
1043
nf->interlaced_uv = 1;
1044
} else {
1045
nf->interlaced = 1;
1046
nf->interlaced_y = 1;
1047
nf->interlaced_uv = 1;
1048
}
1049
break;
1050
1051
case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1052
default:
1053
nf->interlaced = 1;
1054
nf->interlaced_y = 1;
1055
nf->interlaced_uv = 1;
1056
break;
1057
}
1058
1059
if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1060
yi->old_frame_info_args = *nf;
1061
nf->update = 1;
1062
IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
1063
}
1064
1065
nf->update |= update;
1066
nf->sync_field = yi->lace_sync_field;
1067
nf->delay = nf->sync_field != of->sync_field;
1068
}
1069
1070
/* Frame is complete & ready for display */
1071
void ivtv_yuv_frame_complete(struct ivtv *itv)
1072
{
1073
atomic_set(&itv->yuv_info.next_fill_frame,
1074
(itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
1075
}
1076
1077
static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1078
{
1079
DEFINE_WAIT(wait);
1080
int rc = 0;
1081
int got_sig = 0;
1082
/* DMA the frame */
1083
mutex_lock(&itv->udma.lock);
1084
1085
if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
1086
mutex_unlock(&itv->udma.lock);
1087
return rc;
1088
}
1089
1090
ivtv_udma_prepare(itv);
1091
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
1092
/* if no UDMA is pending and no UDMA is in progress, then the DMA
1093
is finished */
1094
while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
1095
test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
1096
/* don't interrupt if the DMA is in progress but break off
1097
a still pending DMA. */
1098
got_sig = signal_pending(current);
1099
if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
1100
break;
1101
got_sig = 0;
1102
schedule();
1103
}
1104
finish_wait(&itv->dma_waitq, &wait);
1105
1106
/* Unmap Last DMA Xfer */
1107
ivtv_udma_unmap(itv);
1108
1109
if (got_sig) {
1110
IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1111
mutex_unlock(&itv->udma.lock);
1112
return -EINTR;
1113
}
1114
1115
ivtv_yuv_frame_complete(itv);
1116
1117
mutex_unlock(&itv->udma.lock);
1118
return rc;
1119
}
1120
1121
/* Setup frame according to V4L2 parameters */
1122
void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
1123
{
1124
struct yuv_playback_info *yi = &itv->yuv_info;
1125
struct ivtv_dma_frame dma_args;
1126
1127
ivtv_yuv_next_free(itv);
1128
1129
/* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1130
dma_args.y_source = NULL;
1131
dma_args.uv_source = NULL;
1132
dma_args.src.left = 0;
1133
dma_args.src.top = 0;
1134
dma_args.src.width = yi->v4l2_src_w;
1135
dma_args.src.height = yi->v4l2_src_h;
1136
dma_args.dst = yi->main_rect;
1137
dma_args.src_width = yi->v4l2_src_w;
1138
dma_args.src_height = yi->v4l2_src_h;
1139
1140
/* ... and use the same setup routine as ivtv_yuv_prep_frame */
1141
ivtv_yuv_setup_frame(itv, &dma_args);
1142
1143
if (!itv->dma_data_req_offset)
1144
itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
1145
}
1146
1147
/* Attempt to dma a frame from a user buffer */
1148
int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
1149
{
1150
struct yuv_playback_info *yi = &itv->yuv_info;
1151
struct ivtv_dma_frame dma_args;
1152
1153
ivtv_yuv_setup_stream_frame(itv);
1154
1155
/* We only need to supply source addresses for this */
1156
dma_args.y_source = src;
1157
dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
1158
return ivtv_yuv_udma_frame(itv, &dma_args);
1159
}
1160
1161
/* IVTV_IOC_DMA_FRAME ioctl handler */
1162
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1163
{
1164
/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1165
1166
ivtv_yuv_next_free(itv);
1167
ivtv_yuv_setup_frame(itv, args);
1168
return ivtv_yuv_udma_frame(itv, args);
1169
}
1170
1171
void ivtv_yuv_close(struct ivtv *itv)
1172
{
1173
struct yuv_playback_info *yi = &itv->yuv_info;
1174
int h_filter, v_filter_1, v_filter_2;
1175
1176
IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1177
ivtv_waitq(&itv->vsync_waitq);
1178
1179
yi->running = 0;
1180
atomic_set(&yi->next_dma_frame, -1);
1181
atomic_set(&yi->next_fill_frame, 0);
1182
1183
/* Reset registers we have changed so mpeg playback works */
1184
1185
/* If we fully restore this register, the display may remain active.
1186
Restore, but set one bit to blank the video. Firmware will always
1187
clear this bit when needed, so not a problem. */
1188
write_reg(yi->reg_2898 | 0x01000000, 0x2898);
1189
1190
write_reg(yi->reg_2834, 0x02834);
1191
write_reg(yi->reg_2838, 0x02838);
1192
write_reg(yi->reg_283c, 0x0283c);
1193
write_reg(yi->reg_2840, 0x02840);
1194
write_reg(yi->reg_2844, 0x02844);
1195
write_reg(yi->reg_2848, 0x02848);
1196
write_reg(yi->reg_2854, 0x02854);
1197
write_reg(yi->reg_285c, 0x0285c);
1198
write_reg(yi->reg_2864, 0x02864);
1199
write_reg(yi->reg_2870, 0x02870);
1200
write_reg(yi->reg_2874, 0x02874);
1201
write_reg(yi->reg_2890, 0x02890);
1202
write_reg(yi->reg_289c, 0x0289c);
1203
1204
write_reg(yi->reg_2918, 0x02918);
1205
write_reg(yi->reg_291c, 0x0291c);
1206
write_reg(yi->reg_2920, 0x02920);
1207
write_reg(yi->reg_2924, 0x02924);
1208
write_reg(yi->reg_2928, 0x02928);
1209
write_reg(yi->reg_292c, 0x0292c);
1210
write_reg(yi->reg_2930, 0x02930);
1211
write_reg(yi->reg_2934, 0x02934);
1212
write_reg(yi->reg_2938, 0x02938);
1213
write_reg(yi->reg_293c, 0x0293c);
1214
write_reg(yi->reg_2940, 0x02940);
1215
write_reg(yi->reg_2944, 0x02944);
1216
write_reg(yi->reg_2948, 0x02948);
1217
write_reg(yi->reg_294c, 0x0294c);
1218
write_reg(yi->reg_2950, 0x02950);
1219
write_reg(yi->reg_2954, 0x02954);
1220
write_reg(yi->reg_2958, 0x02958);
1221
write_reg(yi->reg_295c, 0x0295c);
1222
write_reg(yi->reg_2960, 0x02960);
1223
write_reg(yi->reg_2964, 0x02964);
1224
write_reg(yi->reg_2968, 0x02968);
1225
write_reg(yi->reg_296c, 0x0296c);
1226
write_reg(yi->reg_2970, 0x02970);
1227
1228
/* Prepare to restore filters */
1229
1230
/* First the horizontal filter */
1231
if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
1232
/* An exact size match uses filter 0 */
1233
h_filter = 0;
1234
} else {
1235
/* Figure out which filter to use */
1236
h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
1237
h_filter = (h_filter >> 1) + (h_filter & 1);
1238
/* Only an exact size match can use filter 0. */
1239
h_filter += !h_filter;
1240
}
1241
1242
/* Now the vertical filter */
1243
if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
1244
/* An exact size match uses filter 0/1 */
1245
v_filter_1 = 0;
1246
v_filter_2 = 1;
1247
} else {
1248
/* Figure out which filter to use */
1249
v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
1250
v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1251
/* Only an exact size match can use filter 0 */
1252
v_filter_1 += !v_filter_1;
1253
v_filter_2 = v_filter_1;
1254
}
1255
1256
/* Now restore the filters */
1257
ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
1258
1259
/* and clear a few registers */
1260
write_reg(0, 0x02814);
1261
write_reg(0, 0x0282c);
1262
write_reg(0, 0x02904);
1263
write_reg(0, 0x02910);
1264
1265
/* Release the blanking buffer */
1266
if (yi->blanking_ptr) {
1267
kfree(yi->blanking_ptr);
1268
yi->blanking_ptr = NULL;
1269
pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
1270
}
1271
1272
/* Invalidate the old dimension information */
1273
yi->old_frame_info.src_w = 0;
1274
yi->old_frame_info.src_h = 0;
1275
yi->old_frame_info_args.src_w = 0;
1276
yi->old_frame_info_args.src_h = 0;
1277
1278
/* All done. */
1279
clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
1280
}
1281
1282