cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ivtv-yuv.c (38164B)


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