File Index
Files and directories
Sign in
FILE

ivtv-yuv.c

File preview with syntax highlighting.

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