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