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