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