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