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