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