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