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