0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ivtv-driver.h"
0010 #include "ivtv-udma.h"
0011 #include "ivtv-yuv.h"
0012
0013
0014 const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
0015 0x001a8600,
0016 0x00240400,
0017 0x002d8200,
0018 0x00370000,
0019 0x00029000,
0020 0x000C0E00,
0021 0x006B0400,
0022 0x00748200
0023 };
0024
0025 static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
0026 struct ivtv_dma_frame *args)
0027 {
0028 struct ivtv_dma_page_info y_dma;
0029 struct ivtv_dma_page_info uv_dma;
0030 struct yuv_playback_info *yi = &itv->yuv_info;
0031 u8 frame = yi->draw_frame;
0032 struct yuv_frame_info *f = &yi->new_frame_info[frame];
0033 int y_pages, uv_pages;
0034 unsigned long y_buffer_offset, uv_buffer_offset;
0035 int y_decode_height, uv_decode_height, y_size;
0036
0037 y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
0038 uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
0039
0040 y_decode_height = uv_decode_height = f->src_h + f->src_y;
0041
0042 if (f->offset_y)
0043 y_buffer_offset += 720 * 16;
0044
0045 if (y_decode_height & 15)
0046 y_decode_height = (y_decode_height + 16) & ~15;
0047
0048 if (uv_decode_height & 31)
0049 uv_decode_height = (uv_decode_height + 32) & ~31;
0050
0051 y_size = 720 * y_decode_height;
0052
0053
0054 if (dma->SG_length || dma->page_count) {
0055 IVTV_DEBUG_WARN
0056 ("prep_user_dma: SG_length %d page_count %d still full?\n",
0057 dma->SG_length, dma->page_count);
0058 return -EBUSY;
0059 }
0060
0061 ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height);
0062 ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
0063
0064
0065 y_pages = pin_user_pages_unlocked(y_dma.uaddr,
0066 y_dma.page_count, &dma->map[0], FOLL_FORCE);
0067 uv_pages = 0;
0068 if (y_pages == y_dma.page_count) {
0069 uv_pages = pin_user_pages_unlocked(uv_dma.uaddr,
0070 uv_dma.page_count, &dma->map[y_pages],
0071 FOLL_FORCE);
0072 }
0073
0074 if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
0075 int rc = -EFAULT;
0076
0077 if (y_pages == y_dma.page_count) {
0078 IVTV_DEBUG_WARN
0079 ("failed to map uv user pages, returned %d expecting %d\n",
0080 uv_pages, uv_dma.page_count);
0081
0082 if (uv_pages >= 0) {
0083 unpin_user_pages(&dma->map[y_pages], uv_pages);
0084 rc = -EFAULT;
0085 } else {
0086 rc = uv_pages;
0087 }
0088 } else {
0089 IVTV_DEBUG_WARN
0090 ("failed to map y user pages, returned %d expecting %d\n",
0091 y_pages, y_dma.page_count);
0092 }
0093 if (y_pages >= 0) {
0094 unpin_user_pages(dma->map, y_pages);
0095
0096
0097
0098
0099
0100
0101 } else {
0102 rc = y_pages;
0103 }
0104 return rc;
0105 }
0106
0107 dma->page_count = y_pages + uv_pages;
0108
0109
0110 if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
0111 IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
0112 unpin_user_pages(dma->map, dma->page_count);
0113 dma->page_count = 0;
0114 return -ENOMEM;
0115 }
0116 dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
0117 dma->page_count, DMA_TO_DEVICE);
0118
0119
0120 ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
0121
0122
0123 if (f->offset_y && yi->blanking_dmaptr) {
0124 dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
0125 dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr);
0126 dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
0127 dma->SG_length++;
0128 }
0129
0130
0131 dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
0132
0133 ivtv_udma_sync_for_device(itv);
0134 return 0;
0135 }
0136
0137
0138 int ivtv_yuv_filter_check(struct ivtv *itv)
0139 {
0140 int i, y, uv;
0141
0142 for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) {
0143 if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) ||
0144 (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) {
0145 IVTV_WARN ("YUV filter table not found in firmware.\n");
0146 return -1;
0147 }
0148 }
0149 return 0;
0150 }
0151
0152 static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
0153 {
0154 u32 i, line;
0155
0156
0157 if (h_filter > -1) {
0158 if (h_filter > 4)
0159 h_filter = 4;
0160 i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384);
0161 for (line = 0; line < 16; line++) {
0162 write_reg(read_dec(i), 0x02804);
0163 write_reg(read_dec(i), 0x0281c);
0164 i += 4;
0165 write_reg(read_dec(i), 0x02808);
0166 write_reg(read_dec(i), 0x02820);
0167 i += 4;
0168 write_reg(read_dec(i), 0x0280c);
0169 write_reg(read_dec(i), 0x02824);
0170 i += 4;
0171 write_reg(read_dec(i), 0x02810);
0172 write_reg(read_dec(i), 0x02828);
0173 i += 4;
0174 write_reg(read_dec(i), 0x02814);
0175 write_reg(read_dec(i), 0x0282c);
0176 i += 8;
0177 write_reg(0, 0x02818);
0178 write_reg(0, 0x02830);
0179 }
0180 IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter);
0181 }
0182
0183 if (v_filter_1 > -1) {
0184 if (v_filter_1 > 4)
0185 v_filter_1 = 4;
0186 i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192);
0187 for (line = 0; line < 16; line++) {
0188 write_reg(read_dec(i), 0x02900);
0189 i += 4;
0190 write_reg(read_dec(i), 0x02904);
0191 i += 8;
0192 write_reg(0, 0x02908);
0193 }
0194 IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1);
0195 }
0196
0197 if (v_filter_2 > -1) {
0198 if (v_filter_2 > 4)
0199 v_filter_2 = 4;
0200 i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192);
0201 for (line = 0; line < 16; line++) {
0202 write_reg(read_dec(i), 0x0290c);
0203 i += 4;
0204 write_reg(read_dec(i), 0x02910);
0205 i += 8;
0206 write_reg(0, 0x02914);
0207 }
0208 IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2);
0209 }
0210 }
0211
0212 static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f)
0213 {
0214 struct yuv_playback_info *yi = &itv->yuv_info;
0215 u32 reg_2834, reg_2838, reg_283c;
0216 u32 reg_2844, reg_2854, reg_285c;
0217 u32 reg_2864, reg_2874, reg_2890;
0218 u32 reg_2870, reg_2870_base, reg_2870_offset;
0219 int x_cutoff;
0220 int h_filter;
0221 u32 master_width;
0222
0223 IVTV_DEBUG_WARN
0224 ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
0225 f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x);
0226
0227
0228 x_cutoff = f->src_w + f->src_x;
0229
0230
0231 reg_2834 = f->dst_w;
0232 reg_2838 = reg_2834;
0233
0234
0235 reg_2890 = f->dst_x;
0236
0237
0238 reg_2870 = 0;
0239
0240
0241
0242
0243
0244
0245
0246 if (f->vis_w == 720) {
0247 if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680))
0248 reg_2870 = 10 - (f->tru_x - f->pan_x) / 4;
0249 else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660))
0250 reg_2870 = (10 + (f->tru_x - f->pan_x) / 2);
0251
0252 if (f->dst_w >= f->src_w)
0253 reg_2870 = reg_2870 << 16 | reg_2870;
0254 else
0255 reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
0256 }
0257
0258 if (f->dst_w < f->src_w)
0259 reg_2870 = 0x000d000e - reg_2870;
0260 else
0261 reg_2870 = 0x0012000e - reg_2870;
0262
0263
0264 reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19;
0265
0266 if (f->dst_w >= f->src_w) {
0267 x_cutoff &= ~1;
0268 master_width = (f->src_w * 0x00200000) / (f->dst_w);
0269 if (master_width * f->dst_w != f->src_w * 0x00200000)
0270 master_width++;
0271 reg_2834 = (reg_2834 << 16) | x_cutoff;
0272 reg_2838 = (reg_2838 << 16) | x_cutoff;
0273 reg_283c = master_width >> 2;
0274 reg_2844 = master_width >> 2;
0275 reg_2854 = master_width;
0276 reg_285c = master_width >> 1;
0277 reg_2864 = master_width >> 1;
0278
0279
0280
0281 if (f->dst_w > f->src_w)
0282 reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14);
0283 else
0284 reg_2870_base = 0;
0285
0286 reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
0287 reg_2874 = 0;
0288 } else if (f->dst_w < f->src_w / 2) {
0289 master_width = (f->src_w * 0x00080000) / f->dst_w;
0290 if (master_width * f->dst_w != f->src_w * 0x00080000)
0291 master_width++;
0292 reg_2834 = (reg_2834 << 16) | x_cutoff;
0293 reg_2838 = (reg_2838 << 16) | x_cutoff;
0294 reg_283c = master_width >> 2;
0295 reg_2844 = master_width >> 1;
0296 reg_2854 = master_width;
0297 reg_285c = master_width >> 1;
0298 reg_2864 = master_width >> 1;
0299 reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset;
0300 reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16;
0301 reg_2874 = 0x00000012;
0302 } else {
0303 master_width = (f->src_w * 0x00100000) / f->dst_w;
0304 if (master_width * f->dst_w != f->src_w * 0x00100000)
0305 master_width++;
0306 reg_2834 = (reg_2834 << 16) | x_cutoff;
0307 reg_2838 = (reg_2838 << 16) | x_cutoff;
0308 reg_283c = master_width >> 2;
0309 reg_2844 = master_width >> 1;
0310 reg_2854 = master_width;
0311 reg_285c = master_width >> 1;
0312 reg_2864 = master_width >> 1;
0313 reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1;
0314 reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16;
0315 reg_2874 = 0x00000001;
0316 }
0317
0318
0319 if (f->src_w == f->dst_w) {
0320
0321 h_filter = 0;
0322 } else {
0323
0324 h_filter = ((f->src_w << 16) / f->dst_w) >> 15;
0325 h_filter = (h_filter >> 1) + (h_filter & 1);
0326
0327 h_filter += !h_filter;
0328 }
0329
0330 write_reg(reg_2834, 0x02834);
0331 write_reg(reg_2838, 0x02838);
0332 IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
0333 yi->reg_2834, reg_2834, yi->reg_2838, reg_2838);
0334
0335 write_reg(reg_283c, 0x0283c);
0336 write_reg(reg_2844, 0x02844);
0337
0338 IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
0339 yi->reg_283c, reg_283c, yi->reg_2844, reg_2844);
0340
0341 write_reg(0x00080514, 0x02840);
0342 write_reg(0x00100514, 0x02848);
0343 IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
0344 yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514);
0345
0346 write_reg(reg_2854, 0x02854);
0347 IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
0348 yi->reg_2854, reg_2854);
0349
0350 write_reg(reg_285c, 0x0285c);
0351 write_reg(reg_2864, 0x02864);
0352 IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
0353 yi->reg_285c, reg_285c, yi->reg_2864, reg_2864);
0354
0355 write_reg(reg_2874, 0x02874);
0356 IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
0357 yi->reg_2874, reg_2874);
0358
0359 write_reg(reg_2870, 0x02870);
0360 IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
0361 yi->reg_2870, reg_2870);
0362
0363 write_reg(reg_2890, 0x02890);
0364 IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
0365 yi->reg_2890, reg_2890);
0366
0367
0368 if (h_filter != yi->h_filter) {
0369 ivtv_yuv_filter(itv, h_filter, -1, -1);
0370 yi->h_filter = h_filter;
0371 }
0372 }
0373
0374 static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f)
0375 {
0376 struct yuv_playback_info *yi = &itv->yuv_info;
0377 u32 master_height;
0378 u32 reg_2918, reg_291c, reg_2920, reg_2928;
0379 u32 reg_2930, reg_2934, reg_293c;
0380 u32 reg_2940, reg_2944, reg_294c;
0381 u32 reg_2950, reg_2954, reg_2958, reg_295c;
0382 u32 reg_2960, reg_2964, reg_2968, reg_296c;
0383 u32 reg_289c;
0384 u32 src_major_y, src_minor_y;
0385 u32 src_major_uv, src_minor_uv;
0386 u32 reg_2964_base, reg_2968_base;
0387 int v_filter_1, v_filter_2;
0388
0389 IVTV_DEBUG_WARN
0390 ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
0391 f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y);
0392
0393
0394 IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
0395 f->interlaced_y ? "Interlaced" : "Progressive");
0396
0397 IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
0398 f->interlaced_uv ? "Interlaced" : "Progressive");
0399
0400
0401 IVTV_DEBUG_WARN("Source video: %s\n",
0402 f->interlaced ? "Interlaced" : "Progressive");
0403
0404
0405
0406 if (f->src_y < 8) {
0407 src_minor_uv = f->src_y;
0408 src_major_uv = 0;
0409 } else {
0410 src_minor_uv = 8;
0411 src_major_uv = f->src_y - 8;
0412 }
0413
0414 src_minor_y = src_minor_uv;
0415 src_major_y = src_major_uv;
0416
0417 if (f->offset_y)
0418 src_minor_y += 16;
0419
0420 if (f->interlaced_y)
0421 reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y);
0422 else
0423 reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1);
0424
0425 if (f->interlaced_uv)
0426 reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1);
0427 else
0428 reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv);
0429
0430 reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14;
0431 reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14;
0432
0433 if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) {
0434 master_height = (f->src_h * 0x00400000) / f->dst_h;
0435 if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2)
0436 master_height++;
0437 reg_2920 = master_height >> 2;
0438 reg_2928 = master_height >> 3;
0439 reg_2930 = master_height;
0440 reg_2940 = master_height >> 1;
0441 reg_2964_base >>= 3;
0442 reg_2968_base >>= 3;
0443 reg_296c = 0x00000000;
0444 } else if (f->dst_h >= f->src_h) {
0445 master_height = (f->src_h * 0x00400000) / f->dst_h;
0446 master_height = (master_height >> 1) + (master_height & 1);
0447 reg_2920 = master_height >> 2;
0448 reg_2928 = master_height >> 2;
0449 reg_2930 = master_height;
0450 reg_2940 = master_height >> 1;
0451 reg_296c = 0x00000000;
0452 if (f->interlaced_y) {
0453 reg_2964_base >>= 3;
0454 } else {
0455 reg_296c++;
0456 reg_2964_base >>= 2;
0457 }
0458 if (f->interlaced_uv)
0459 reg_2928 >>= 1;
0460 reg_2968_base >>= 3;
0461 } else if (f->dst_h >= f->src_h / 2) {
0462 master_height = (f->src_h * 0x00200000) / f->dst_h;
0463 master_height = (master_height >> 1) + (master_height & 1);
0464 reg_2920 = master_height >> 2;
0465 reg_2928 = master_height >> 2;
0466 reg_2930 = master_height;
0467 reg_2940 = master_height;
0468 reg_296c = 0x00000101;
0469 if (f->interlaced_y) {
0470 reg_2964_base >>= 2;
0471 } else {
0472 reg_296c++;
0473 reg_2964_base >>= 1;
0474 }
0475 if (f->interlaced_uv)
0476 reg_2928 >>= 1;
0477 reg_2968_base >>= 2;
0478 } else {
0479 master_height = (f->src_h * 0x00100000) / f->dst_h;
0480 master_height = (master_height >> 1) + (master_height & 1);
0481 reg_2920 = master_height >> 2;
0482 reg_2928 = master_height >> 2;
0483 reg_2930 = master_height;
0484 reg_2940 = master_height;
0485 reg_2964_base >>= 1;
0486 reg_2968_base >>= 2;
0487 reg_296c = 0x00000102;
0488 }
0489
0490
0491
0492 if (f->src_h == f->dst_h) {
0493 reg_2934 = 0x00020000;
0494 reg_293c = 0x00100000;
0495 reg_2944 = 0x00040000;
0496 reg_294c = 0x000b0000;
0497 } else {
0498 reg_2934 = 0x00000FF0;
0499 reg_293c = 0x00000FF0;
0500 reg_2944 = 0x00000FF0;
0501 reg_294c = 0x00000FF0;
0502 }
0503
0504
0505 reg_2950 = 0x00010000 + src_major_y;
0506 if (f->interlaced_y)
0507 reg_2950 += 0x00010000;
0508 reg_2954 = reg_2950 + 1;
0509
0510 reg_2958 = 0x00010000 + (src_major_y >> 1);
0511 if (f->interlaced_uv)
0512 reg_2958 += 0x00010000;
0513 reg_295c = reg_2958 + 1;
0514
0515 if (yi->decode_height == 480)
0516 reg_289c = 0x011e0017;
0517 else
0518 reg_289c = 0x01500017;
0519
0520 if (f->dst_y < 0)
0521 reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);
0522 else
0523 reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1);
0524
0525
0526
0527 reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) |
0528 (((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15);
0529
0530
0531 if (f->src_h == f->dst_h) {
0532 reg_2964 = 1;
0533 } else {
0534 reg_2964 = 2 + ((f->dst_h << 1) / f->src_h);
0535 reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);
0536 }
0537 reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);
0538 reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
0539
0540
0541
0542
0543 reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
0544 reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
0545
0546
0547
0548
0549 if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h))
0550 reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2);
0551
0552 if (!f->interlaced_y)
0553 reg_2964 -= 0x00010001;
0554 if (!f->interlaced_uv)
0555 reg_2968 -= 0x00010001;
0556
0557 reg_2964 += ((reg_2964_base << 16) | reg_2964_base);
0558 reg_2968 += ((reg_2968_base << 16) | reg_2968_base);
0559
0560
0561 if (f->src_h == f->dst_h) {
0562
0563 v_filter_1 = 0;
0564 v_filter_2 = 1;
0565 } else {
0566
0567 v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15;
0568 v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
0569
0570 v_filter_1 += !v_filter_1;
0571 v_filter_2 = v_filter_1;
0572 }
0573
0574 write_reg(reg_2934, 0x02934);
0575 write_reg(reg_293c, 0x0293c);
0576 IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
0577 yi->reg_2934, reg_2934, yi->reg_293c, reg_293c);
0578 write_reg(reg_2944, 0x02944);
0579 write_reg(reg_294c, 0x0294c);
0580 IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
0581 yi->reg_2944, reg_2944, yi->reg_294c, reg_294c);
0582
0583
0584
0585
0586
0587 write_reg(reg_2930, 0x02938);
0588 write_reg(reg_2930, 0x02930);
0589 IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
0590 yi->reg_2930, reg_2930, yi->reg_2938, reg_2930);
0591
0592 write_reg(reg_2928, 0x02928);
0593 write_reg(reg_2928 + 0x514, 0x0292C);
0594 IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
0595 yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514);
0596
0597 write_reg(reg_2920, 0x02920);
0598 write_reg(reg_2920 + 0x514, 0x02924);
0599 IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
0600 yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514);
0601
0602 write_reg(reg_2918, 0x02918);
0603 write_reg(reg_291c, 0x0291C);
0604 IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
0605 yi->reg_2918, reg_2918, yi->reg_291c, reg_291c);
0606
0607 write_reg(reg_296c, 0x0296c);
0608 IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
0609 yi->reg_296c, reg_296c);
0610
0611 write_reg(reg_2940, 0x02948);
0612 write_reg(reg_2940, 0x02940);
0613 IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
0614 yi->reg_2940, reg_2940, yi->reg_2948, reg_2940);
0615
0616 write_reg(reg_2950, 0x02950);
0617 write_reg(reg_2954, 0x02954);
0618 IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
0619 yi->reg_2950, reg_2950, yi->reg_2954, reg_2954);
0620
0621 write_reg(reg_2958, 0x02958);
0622 write_reg(reg_295c, 0x0295C);
0623 IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
0624 yi->reg_2958, reg_2958, yi->reg_295c, reg_295c);
0625
0626 write_reg(reg_2960, 0x02960);
0627 IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
0628 yi->reg_2960, reg_2960);
0629
0630 write_reg(reg_2964, 0x02964);
0631 write_reg(reg_2968, 0x02968);
0632 IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
0633 yi->reg_2964, reg_2964, yi->reg_2968, reg_2968);
0634
0635 write_reg(reg_289c, 0x0289c);
0636 IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
0637 yi->reg_289c, reg_289c);
0638
0639
0640 if (v_filter_1 != yi->v_filter_1) {
0641 ivtv_yuv_filter(itv, -1, v_filter_1, -1);
0642 yi->v_filter_1 = v_filter_1;
0643 }
0644
0645
0646 if (v_filter_2 != yi->v_filter_2) {
0647 ivtv_yuv_filter(itv, -1, -1, v_filter_2);
0648 yi->v_filter_2 = v_filter_2;
0649 }
0650 }
0651
0652
0653 static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
0654 {
0655 struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;
0656 int osd_crop;
0657 u32 osd_scale;
0658 u32 yuv_update = 0;
0659
0660
0661 if (f->src_x < 0)
0662 f->src_x = 0;
0663 if (f->src_y < 0)
0664 f->src_y = 0;
0665
0666
0667 if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {
0668 f->src_x += osd_crop / 2;
0669 f->src_w = (f->src_w - osd_crop) & ~3;
0670 f->dst_w = f->src_w / 4;
0671 f->dst_w += f->dst_w & 1;
0672 }
0673
0674
0675 if (f->src_h / f->dst_h >= 2) {
0676
0677
0678 f->interlaced_y = 1;
0679
0680 if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {
0681
0682 f->src_y += osd_crop / 2;
0683 f->src_h = (f->src_h - osd_crop) & ~3;
0684 f->dst_h = f->src_h / 4;
0685 f->dst_h += f->dst_h & 1;
0686 }
0687 }
0688
0689
0690 if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
0691 (int)f->src_w <= 2 || (int)f->src_h <= 2) {
0692 return IVTV_YUV_UPDATE_INVALID;
0693 }
0694
0695
0696 osd_scale = (f->src_h << 16) / f->dst_h;
0697
0698 if ((osd_crop = f->pan_y - f->dst_y) > 0) {
0699
0700 f->src_y += (osd_scale * osd_crop) >> 16;
0701 f->src_h -= (osd_scale * osd_crop) >> 16;
0702 f->dst_h -= osd_crop;
0703 f->dst_y = 0;
0704 } else {
0705 f->dst_y -= f->pan_y;
0706 }
0707
0708 if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {
0709
0710 f->dst_h -= osd_crop;
0711 f->src_h -= (osd_scale * osd_crop) >> 16;
0712 }
0713
0714 osd_scale = (f->src_w << 16) / f->dst_w;
0715
0716 if ((osd_crop = f->pan_x - f->dst_x) > 0) {
0717
0718 f->src_x += (osd_scale * osd_crop) >> 16;
0719 f->src_w -= (osd_scale * osd_crop) >> 16;
0720 f->dst_w -= osd_crop;
0721 f->dst_x = 0;
0722 } else {
0723 f->dst_x -= f->pan_x;
0724 }
0725
0726 if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {
0727
0728 f->dst_w -= osd_crop;
0729 f->src_w -= (osd_scale * osd_crop) >> 16;
0730 }
0731
0732 if (itv->yuv_info.track_osd) {
0733
0734 f->dst_x += itv->yuv_info.osd_x_offset;
0735 f->dst_y += itv->yuv_info.osd_y_offset;
0736 }
0737
0738
0739
0740 f->dst_w &= ~1;
0741 f->dst_x &= ~1;
0742
0743 f->src_w += f->src_x & 1;
0744 f->src_x &= ~1;
0745
0746 f->src_w &= ~1;
0747 f->dst_w &= ~1;
0748
0749 f->dst_h &= ~1;
0750 f->dst_y &= ~1;
0751
0752 f->src_h += f->src_y & 1;
0753 f->src_y &= ~1;
0754
0755 f->src_h &= ~1;
0756 f->dst_h &= ~1;
0757
0758
0759
0760
0761 if (f->dst_w < f->src_w / 4) {
0762 f->src_w &= ~3;
0763 f->dst_w = f->src_w / 4;
0764 f->dst_w += f->dst_w & 1;
0765 }
0766 if (f->dst_h < f->src_h / 4) {
0767 f->src_h &= ~3;
0768 f->dst_h = f->src_h / 4;
0769 f->dst_h += f->dst_h & 1;
0770 }
0771
0772
0773 if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
0774 (int)f->src_w <= 2 || (int)f->src_h <= 2) {
0775 return IVTV_YUV_UPDATE_INVALID;
0776 }
0777
0778
0779 if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
0780 (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
0781 (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
0782 yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
0783 }
0784
0785 if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
0786 (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
0787 (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
0788 (of->lace_mode != f->lace_mode) ||
0789 (of->interlaced_y != f->interlaced_y) ||
0790 (of->interlaced_uv != f->interlaced_uv)) {
0791 yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
0792 }
0793
0794 return yuv_update;
0795 }
0796
0797
0798 void ivtv_yuv_work_handler(struct ivtv *itv)
0799 {
0800 struct yuv_playback_info *yi = &itv->yuv_info;
0801 struct yuv_frame_info f;
0802 int frame = yi->update_frame;
0803 u32 yuv_update;
0804
0805 IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
0806 f = yi->new_frame_info[frame];
0807
0808 if (yi->track_osd) {
0809
0810 f.pan_x = yi->osd_x_pan;
0811 f.pan_y = yi->osd_y_pan;
0812 f.vis_w = yi->osd_vis_w;
0813 f.vis_h = yi->osd_vis_h;
0814 } else {
0815
0816 f.pan_x = 0;
0817 f.pan_y = 0;
0818 f.vis_w = 720;
0819 f.vis_h = yi->decode_height;
0820 }
0821
0822
0823 if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
0824 return;
0825
0826 if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
0827 write_reg(0x01008080, 0x2898);
0828 } else if (yuv_update) {
0829 write_reg(0x00108080, 0x2898);
0830
0831 if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
0832 ivtv_yuv_handle_horizontal(itv, &f);
0833
0834 if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
0835 ivtv_yuv_handle_vertical(itv, &f);
0836 }
0837 yi->old_frame_info = f;
0838 }
0839
0840 static void ivtv_yuv_init(struct ivtv *itv)
0841 {
0842 struct yuv_playback_info *yi = &itv->yuv_info;
0843
0844 IVTV_DEBUG_YUV("ivtv_yuv_init\n");
0845
0846
0847 yi->reg_2834 = read_reg(0x02834);
0848 yi->reg_2838 = read_reg(0x02838);
0849 yi->reg_283c = read_reg(0x0283c);
0850 yi->reg_2840 = read_reg(0x02840);
0851 yi->reg_2844 = read_reg(0x02844);
0852 yi->reg_2848 = read_reg(0x02848);
0853 yi->reg_2854 = read_reg(0x02854);
0854 yi->reg_285c = read_reg(0x0285c);
0855 yi->reg_2864 = read_reg(0x02864);
0856 yi->reg_2870 = read_reg(0x02870);
0857 yi->reg_2874 = read_reg(0x02874);
0858 yi->reg_2898 = read_reg(0x02898);
0859 yi->reg_2890 = read_reg(0x02890);
0860
0861 yi->reg_289c = read_reg(0x0289c);
0862 yi->reg_2918 = read_reg(0x02918);
0863 yi->reg_291c = read_reg(0x0291c);
0864 yi->reg_2920 = read_reg(0x02920);
0865 yi->reg_2924 = read_reg(0x02924);
0866 yi->reg_2928 = read_reg(0x02928);
0867 yi->reg_292c = read_reg(0x0292c);
0868 yi->reg_2930 = read_reg(0x02930);
0869 yi->reg_2934 = read_reg(0x02934);
0870 yi->reg_2938 = read_reg(0x02938);
0871 yi->reg_293c = read_reg(0x0293c);
0872 yi->reg_2940 = read_reg(0x02940);
0873 yi->reg_2944 = read_reg(0x02944);
0874 yi->reg_2948 = read_reg(0x02948);
0875 yi->reg_294c = read_reg(0x0294c);
0876 yi->reg_2950 = read_reg(0x02950);
0877 yi->reg_2954 = read_reg(0x02954);
0878 yi->reg_2958 = read_reg(0x02958);
0879 yi->reg_295c = read_reg(0x0295c);
0880 yi->reg_2960 = read_reg(0x02960);
0881 yi->reg_2964 = read_reg(0x02964);
0882 yi->reg_2968 = read_reg(0x02968);
0883 yi->reg_296c = read_reg(0x0296c);
0884 yi->reg_2970 = read_reg(0x02970);
0885
0886 yi->v_filter_1 = -1;
0887 yi->v_filter_2 = -1;
0888 yi->h_filter = -1;
0889
0890
0891 yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
0892 yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
0893
0894
0895
0896 if (read_reg(0x2878) & 4)
0897 yi->decode_height = 576;
0898 else
0899 yi->decode_height = 480;
0900
0901 if (!itv->osd_info) {
0902 yi->osd_vis_w = 720 - yi->osd_x_offset;
0903 yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
0904 } else {
0905
0906 if (!yi->osd_vis_w)
0907 yi->osd_vis_w = 720 - yi->osd_x_offset;
0908
0909 if (!yi->osd_vis_h) {
0910 yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
0911 } else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
0912
0913
0914 IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
0915 yi->osd_vis_h + yi->osd_y_offset,
0916 yi->decode_height);
0917 yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
0918 }
0919 }
0920
0921
0922 yi->blanking_ptr = kzalloc(720 * 16, GFP_ATOMIC|__GFP_NOWARN);
0923 if (yi->blanking_ptr) {
0924 yi->blanking_dmaptr = dma_map_single(&itv->pdev->dev,
0925 yi->blanking_ptr,
0926 720 * 16, DMA_TO_DEVICE);
0927 } else {
0928 yi->blanking_dmaptr = 0;
0929 IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
0930 }
0931
0932
0933 write_reg_sync(0x01, IVTV_REG_VDM);
0934
0935 set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
0936 atomic_set(&yi->next_dma_frame, 0);
0937 }
0938
0939
0940 static void ivtv_yuv_next_free(struct ivtv *itv)
0941 {
0942 int draw, display;
0943 struct yuv_playback_info *yi = &itv->yuv_info;
0944
0945 if (atomic_read(&yi->next_dma_frame) == -1)
0946 ivtv_yuv_init(itv);
0947
0948 draw = atomic_read(&yi->next_fill_frame);
0949 display = atomic_read(&yi->next_dma_frame);
0950
0951 if (display > draw)
0952 display -= IVTV_YUV_BUFFERS;
0953
0954 if (draw - display >= yi->max_frames_buffered)
0955 draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
0956 else
0957 yi->new_frame_info[draw].update = 0;
0958
0959 yi->draw_frame = draw;
0960 }
0961
0962
0963 static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
0964 {
0965 struct yuv_playback_info *yi = &itv->yuv_info;
0966 u8 frame = yi->draw_frame;
0967 u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
0968 struct yuv_frame_info *nf = &yi->new_frame_info[frame];
0969 struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
0970 int lace_threshold = yi->lace_threshold;
0971
0972
0973 int update = nf->update;
0974
0975
0976 nf->src_x = args->src.left;
0977 nf->src_y = args->src.top;
0978 nf->src_w = args->src.width;
0979 nf->src_h = args->src.height;
0980 nf->dst_x = args->dst.left;
0981 nf->dst_y = args->dst.top;
0982 nf->dst_w = args->dst.width;
0983 nf->dst_h = args->dst.height;
0984 nf->tru_x = args->dst.left;
0985 nf->tru_w = args->src_width;
0986 nf->tru_h = args->src_height;
0987
0988
0989 nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
0990
0991 nf->update = 0;
0992 nf->interlaced_y = 0;
0993 nf->interlaced_uv = 0;
0994 nf->delay = 0;
0995 nf->sync_field = 0;
0996 nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
0997
0998 if (lace_threshold < 0)
0999 lace_threshold = yi->decode_height - 1;
1000
1001
1002 switch (nf->lace_mode) {
1003 case IVTV_YUV_MODE_PROGRESSIVE:
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:
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
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
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
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
1078
1079 while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
1080 test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
1081
1082
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
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
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
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
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
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
1142 dma_args.y_source = src;
1143 dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
1144
1145
1146
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
1154 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1155 {
1156 int res;
1157
1158
1159 ivtv_yuv_next_free(itv);
1160 ivtv_yuv_setup_frame(itv, args);
1161
1162
1163
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
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
1185
1186
1187
1188
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
1230
1231
1232 if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
1233
1234 h_filter = 0;
1235 } else {
1236
1237 h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
1238 h_filter = (h_filter >> 1) + (h_filter & 1);
1239
1240 h_filter += !h_filter;
1241 }
1242
1243
1244 if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
1245
1246 v_filter_1 = 0;
1247 v_filter_2 = 1;
1248 } else {
1249
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
1253 v_filter_1 += !v_filter_1;
1254 v_filter_2 = v_filter_1;
1255 }
1256
1257
1258 ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
1259
1260
1261 write_reg(0, 0x02814);
1262 write_reg(0, 0x0282c);
1263 write_reg(0, 0x02904);
1264 write_reg(0, 0x02910);
1265
1266
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
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
1281 clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
1282 }