brintos

brintos / linux-shallow public Read only

0
0
Text · 49.2 KiB · 56b4481 Raw
1865 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *4 * device driver for philips saa7134 based TV cards5 * video4linux video interface6 *7 * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]8 */9 10#include "saa7134.h"11#include "saa7134-reg.h"12 13#include <linux/init.h>14#include <linux/list.h>15#include <linux/module.h>16#include <linux/kernel.h>17#include <linux/slab.h>18#include <linux/sort.h>19 20#include <media/v4l2-common.h>21#include <media/v4l2-event.h>22#include <media/i2c/saa6588.h>23 24/* ------------------------------------------------------------------ */25 26unsigned int video_debug;27static unsigned int gbuffers      = 8;28static unsigned int noninterlaced; /* 0 */29static unsigned int gbufsize      = 720*576*4;30static unsigned int gbufsize_max  = 720*576*4;31static char secam[] = "--";32module_param(video_debug, int, 0644);33MODULE_PARM_DESC(video_debug,"enable debug messages [video]");34module_param(gbuffers, int, 0444);35MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");36module_param(noninterlaced, int, 0644);37MODULE_PARM_DESC(noninterlaced,"capture non interlaced video");38module_param_string(secam, secam, sizeof(secam), 0644);39MODULE_PARM_DESC(secam, "force SECAM variant, either DK,L or Lc");40 41 42#define video_dbg(fmt, arg...) do { \43	if (video_debug & 0x04) \44		printk(KERN_DEBUG pr_fmt("video: " fmt), ## arg); \45	} while (0)46 47/* ------------------------------------------------------------------ */48/* Defines for Video Output Port Register at address 0x191            */49 50/* Bit 0: VIP code T bit polarity */51 52#define VP_T_CODE_P_NON_INVERTED	0x0053#define VP_T_CODE_P_INVERTED		0x0154 55/* ------------------------------------------------------------------ */56/* Defines for Video Output Port Register at address 0x195            */57 58/* Bit 2: Video output clock delay control */59 60#define VP_CLK_CTRL2_NOT_DELAYED	0x0061#define VP_CLK_CTRL2_DELAYED		0x0462 63/* Bit 1: Video output clock invert control */64 65#define VP_CLK_CTRL1_NON_INVERTED	0x0066#define VP_CLK_CTRL1_INVERTED		0x0267 68/* ------------------------------------------------------------------ */69/* Defines for Video Output Port Register at address 0x196            */70 71/* Bits 2 to 0: VSYNC pin video vertical sync type */72 73#define VP_VS_TYPE_MASK			0x0774 75#define VP_VS_TYPE_OFF			0x0076#define VP_VS_TYPE_V123			0x0177#define VP_VS_TYPE_V_ITU		0x0278#define VP_VS_TYPE_VGATE_L		0x0379#define VP_VS_TYPE_RESERVED1		0x0480#define VP_VS_TYPE_RESERVED2		0x0581#define VP_VS_TYPE_F_ITU		0x0682#define VP_VS_TYPE_SC_FID		0x0783 84/* ------------------------------------------------------------------ */85/* data structs for video                                             */86 87static int video_out[][9] = {88	[CCIR656] = { 0x00, 0xb1, 0x00, 0xa1, 0x00, 0x04, 0x06, 0x00, 0x00 },89};90 91static struct saa7134_format formats[] = {92	{93		.fourcc   = V4L2_PIX_FMT_GREY,94		.depth    = 8,95		.pm       = 0x06,96	},{97		.fourcc   = V4L2_PIX_FMT_RGB555,98		.depth    = 16,99		.pm       = 0x13 | 0x80,100	},{101		.fourcc   = V4L2_PIX_FMT_RGB555X,102		.depth    = 16,103		.pm       = 0x13 | 0x80,104		.bswap    = 1,105	},{106		.fourcc   = V4L2_PIX_FMT_RGB565,107		.depth    = 16,108		.pm       = 0x10 | 0x80,109	},{110		.fourcc   = V4L2_PIX_FMT_RGB565X,111		.depth    = 16,112		.pm       = 0x10 | 0x80,113		.bswap    = 1,114	},{115		.fourcc   = V4L2_PIX_FMT_BGR24,116		.depth    = 24,117		.pm       = 0x11,118	},{119		.fourcc   = V4L2_PIX_FMT_RGB24,120		.depth    = 24,121		.pm       = 0x11,122		.bswap    = 1,123	},{124		.fourcc   = V4L2_PIX_FMT_BGR32,125		.depth    = 32,126		.pm       = 0x12,127	},{128		.fourcc   = V4L2_PIX_FMT_RGB32,129		.depth    = 32,130		.pm       = 0x12,131		.bswap    = 1,132		.wswap    = 1,133	},{134		.fourcc   = V4L2_PIX_FMT_YUYV,135		.depth    = 16,136		.pm       = 0x00,137		.bswap    = 1,138		.yuv      = 1,139	},{140		.fourcc   = V4L2_PIX_FMT_UYVY,141		.depth    = 16,142		.pm       = 0x00,143		.yuv      = 1,144	},{145		.fourcc   = V4L2_PIX_FMT_YUV422P,146		.depth    = 16,147		.pm       = 0x09,148		.yuv      = 1,149		.planar   = 1,150		.hshift   = 1,151		.vshift   = 0,152	},{153		.fourcc   = V4L2_PIX_FMT_YUV420,154		.depth    = 12,155		.pm       = 0x0a,156		.yuv      = 1,157		.planar   = 1,158		.hshift   = 1,159		.vshift   = 1,160	},{161		.fourcc   = V4L2_PIX_FMT_YVU420,162		.depth    = 12,163		.pm       = 0x0a,164		.yuv      = 1,165		.planar   = 1,166		.uvswap   = 1,167		.hshift   = 1,168		.vshift   = 1,169	}170};171#define FORMATS ARRAY_SIZE(formats)172 173#define NORM_625_50			\174		.h_start       = 0,	\175		.h_stop        = 719,	\176		.video_v_start = 24,	\177		.video_v_stop  = 311,	\178		.vbi_v_start_0 = 7,	\179		.vbi_v_stop_0  = 23,	\180		.vbi_v_start_1 = 319,   \181		.src_timing    = 4182 183#define NORM_525_60			\184		.h_start       = 0,	\185		.h_stop        = 719,	\186		.video_v_start = 23,	\187		.video_v_stop  = 262,	\188		.vbi_v_start_0 = 10,	\189		.vbi_v_stop_0  = 21,	\190		.vbi_v_start_1 = 273,	\191		.src_timing    = 7192 193static struct saa7134_tvnorm tvnorms[] = {194	{195		.name          = "PAL", /* autodetect */196		.id            = V4L2_STD_PAL,197		NORM_625_50,198 199		.sync_control  = 0x18,200		.luma_control  = 0x40,201		.chroma_ctrl1  = 0x81,202		.chroma_gain   = 0x2a,203		.chroma_ctrl2  = 0x06,204		.vgate_misc    = 0x1c,205 206	},{207		.name          = "PAL-BG",208		.id            = V4L2_STD_PAL_BG,209		NORM_625_50,210 211		.sync_control  = 0x18,212		.luma_control  = 0x40,213		.chroma_ctrl1  = 0x81,214		.chroma_gain   = 0x2a,215		.chroma_ctrl2  = 0x06,216		.vgate_misc    = 0x1c,217 218	},{219		.name          = "PAL-I",220		.id            = V4L2_STD_PAL_I,221		NORM_625_50,222 223		.sync_control  = 0x18,224		.luma_control  = 0x40,225		.chroma_ctrl1  = 0x81,226		.chroma_gain   = 0x2a,227		.chroma_ctrl2  = 0x06,228		.vgate_misc    = 0x1c,229 230	},{231		.name          = "PAL-DK",232		.id            = V4L2_STD_PAL_DK,233		NORM_625_50,234 235		.sync_control  = 0x18,236		.luma_control  = 0x40,237		.chroma_ctrl1  = 0x81,238		.chroma_gain   = 0x2a,239		.chroma_ctrl2  = 0x06,240		.vgate_misc    = 0x1c,241 242	},{243		.name          = "NTSC",244		.id            = V4L2_STD_NTSC,245		NORM_525_60,246 247		.sync_control  = 0x59,248		.luma_control  = 0x40,249		.chroma_ctrl1  = 0x89,250		.chroma_gain   = 0x2a,251		.chroma_ctrl2  = 0x0e,252		.vgate_misc    = 0x18,253 254	},{255		.name          = "SECAM",256		.id            = V4L2_STD_SECAM,257		NORM_625_50,258 259		.sync_control  = 0x18,260		.luma_control  = 0x1b,261		.chroma_ctrl1  = 0xd1,262		.chroma_gain   = 0x80,263		.chroma_ctrl2  = 0x00,264		.vgate_misc    = 0x1c,265 266	},{267		.name          = "SECAM-DK",268		.id            = V4L2_STD_SECAM_DK,269		NORM_625_50,270 271		.sync_control  = 0x18,272		.luma_control  = 0x1b,273		.chroma_ctrl1  = 0xd1,274		.chroma_gain   = 0x80,275		.chroma_ctrl2  = 0x00,276		.vgate_misc    = 0x1c,277 278	},{279		.name          = "SECAM-L",280		.id            = V4L2_STD_SECAM_L,281		NORM_625_50,282 283		.sync_control  = 0x18,284		.luma_control  = 0x1b,285		.chroma_ctrl1  = 0xd1,286		.chroma_gain   = 0x80,287		.chroma_ctrl2  = 0x00,288		.vgate_misc    = 0x1c,289 290	},{291		.name          = "SECAM-Lc",292		.id            = V4L2_STD_SECAM_LC,293		NORM_625_50,294 295		.sync_control  = 0x18,296		.luma_control  = 0x1b,297		.chroma_ctrl1  = 0xd1,298		.chroma_gain   = 0x80,299		.chroma_ctrl2  = 0x00,300		.vgate_misc    = 0x1c,301 302	},{303		.name          = "PAL-M",304		.id            = V4L2_STD_PAL_M,305		NORM_525_60,306 307		.sync_control  = 0x59,308		.luma_control  = 0x40,309		.chroma_ctrl1  = 0xb9,310		.chroma_gain   = 0x2a,311		.chroma_ctrl2  = 0x0e,312		.vgate_misc    = 0x18,313 314	},{315		.name          = "PAL-Nc",316		.id            = V4L2_STD_PAL_Nc,317		NORM_625_50,318 319		.sync_control  = 0x18,320		.luma_control  = 0x40,321		.chroma_ctrl1  = 0xa1,322		.chroma_gain   = 0x2a,323		.chroma_ctrl2  = 0x06,324		.vgate_misc    = 0x1c,325 326	},{327		.name          = "PAL-60",328		.id            = V4L2_STD_PAL_60,329 330		.h_start       = 0,331		.h_stop        = 719,332		.video_v_start = 23,333		.video_v_stop  = 262,334		.vbi_v_start_0 = 10,335		.vbi_v_stop_0  = 21,336		.vbi_v_start_1 = 273,337		.src_timing    = 7,338 339		.sync_control  = 0x18,340		.luma_control  = 0x40,341		.chroma_ctrl1  = 0x81,342		.chroma_gain   = 0x2a,343		.chroma_ctrl2  = 0x06,344		.vgate_misc    = 0x1c,345	}346};347#define TVNORMS ARRAY_SIZE(tvnorms)348 349static struct saa7134_format* format_by_fourcc(unsigned int fourcc)350{351	unsigned int i;352 353	for (i = 0; i < FORMATS; i++)354		if (formats[i].fourcc == fourcc)355			return formats+i;356	return NULL;357}358 359/* ------------------------------------------------------------------ */360 361static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)362{363	video_dbg("set tv norm = %s\n", norm->name);364	dev->tvnorm = norm;365 366	/* setup cropping */367	dev->crop_bounds.left    = norm->h_start;368	dev->crop_defrect.left   = norm->h_start;369	dev->crop_bounds.width   = norm->h_stop - norm->h_start +1;370	dev->crop_defrect.width  = norm->h_stop - norm->h_start +1;371 372	dev->crop_bounds.top     = (norm->vbi_v_stop_0+1)*2;373	dev->crop_defrect.top    = norm->video_v_start*2;374	dev->crop_bounds.height  = ((norm->id & V4L2_STD_525_60) ? 524 : 624)375		- dev->crop_bounds.top;376	dev->crop_defrect.height = (norm->video_v_stop - norm->video_v_start +1)*2;377 378	dev->crop_current = dev->crop_defrect;379 380	saa7134_set_tvnorm_hw(dev);381}382 383static void video_mux(struct saa7134_dev *dev, int input)384{385	video_dbg("video input = %d [%s]\n",386		  input, saa7134_input_name[card_in(dev, input).type]);387	dev->ctl_input = input;388	set_tvnorm(dev, dev->tvnorm);389	saa7134_tvaudio_setinput(dev, &card_in(dev, input));390}391 392 393static void saa7134_set_decoder(struct saa7134_dev *dev)394{395	int luma_control, sync_control, chroma_ctrl1, mux;396 397	struct saa7134_tvnorm *norm = dev->tvnorm;398	mux = card_in(dev, dev->ctl_input).vmux;399 400	luma_control = norm->luma_control;401	sync_control = norm->sync_control;402	chroma_ctrl1 = norm->chroma_ctrl1;403 404	if (mux > 5)405		luma_control |= 0x80; /* svideo */406	if (noninterlaced || dev->nosignal)407		sync_control |= 0x20;408 409	/* switch on auto standard detection */410	sync_control |= SAA7134_SYNC_CTRL_AUFD;411	chroma_ctrl1 |= SAA7134_CHROMA_CTRL1_AUTO0;412	chroma_ctrl1 &= ~SAA7134_CHROMA_CTRL1_FCTC;413	luma_control &= ~SAA7134_LUMA_CTRL_LDEL;414 415	/* setup video decoder */416	saa_writeb(SAA7134_INCR_DELAY,            0x08);417	saa_writeb(SAA7134_ANALOG_IN_CTRL1,       0xc0 | mux);418	saa_writeb(SAA7134_ANALOG_IN_CTRL2,       0x00);419 420	saa_writeb(SAA7134_ANALOG_IN_CTRL3,       0x90);421	saa_writeb(SAA7134_ANALOG_IN_CTRL4,       0x90);422	saa_writeb(SAA7134_HSYNC_START,           0xeb);423	saa_writeb(SAA7134_HSYNC_STOP,            0xe0);424	saa_writeb(SAA7134_SOURCE_TIMING1,        norm->src_timing);425 426	saa_writeb(SAA7134_SYNC_CTRL,             sync_control);427	saa_writeb(SAA7134_LUMA_CTRL,             luma_control);428	saa_writeb(SAA7134_DEC_LUMA_BRIGHT,       dev->ctl_bright);429 430	saa_writeb(SAA7134_DEC_LUMA_CONTRAST,431		dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);432 433	saa_writeb(SAA7134_DEC_CHROMA_SATURATION,434		dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);435 436	saa_writeb(SAA7134_DEC_CHROMA_HUE,        dev->ctl_hue);437	saa_writeb(SAA7134_CHROMA_CTRL1,          chroma_ctrl1);438	saa_writeb(SAA7134_CHROMA_GAIN,           norm->chroma_gain);439 440	saa_writeb(SAA7134_CHROMA_CTRL2,          norm->chroma_ctrl2);441	saa_writeb(SAA7134_MODE_DELAY_CTRL,       0x00);442 443	saa_writeb(SAA7134_ANALOG_ADC,            0x01);444	saa_writeb(SAA7134_VGATE_START,           0x11);445	saa_writeb(SAA7134_VGATE_STOP,            0xfe);446	saa_writeb(SAA7134_MISC_VGATE_MSB,        norm->vgate_misc);447	saa_writeb(SAA7134_RAW_DATA_GAIN,         0x40);448	saa_writeb(SAA7134_RAW_DATA_OFFSET,       0x80);449}450 451void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)452{453	saa7134_set_decoder(dev);454 455	saa_call_all(dev, video, s_std, dev->tvnorm->id);456	/* Set the correct norm for the saa6752hs. This function457	   does nothing if there is no saa6752hs. */458	saa_call_empress(dev, video, s_std, dev->tvnorm->id);459}460 461static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)462{463	static const struct {464		int xpsc;465		int xacl;466		int xc2_1;467		int xdcg;468		int vpfy;469	} vals[] = {470		/* XPSC XACL XC2_1 XDCG VPFY */471		{    1,   0,    0,    0,   0 },472		{    2,   2,    1,    2,   2 },473		{    3,   4,    1,    3,   2 },474		{    4,   8,    1,    4,   2 },475		{    5,   8,    1,    4,   2 },476		{    6,   8,    1,    4,   3 },477		{    7,   8,    1,    4,   3 },478		{    8,  15,    0,    4,   3 },479		{    9,  15,    0,    4,   3 },480		{   10,  16,    1,    5,   3 },481	};482	static const int count = ARRAY_SIZE(vals);483	int i;484 485	for (i = 0; i < count; i++)486		if (vals[i].xpsc == prescale)487			break;488	if (i == count)489		return;490 491	saa_writeb(SAA7134_H_PRESCALE(task), vals[i].xpsc);492	saa_writeb(SAA7134_ACC_LENGTH(task), vals[i].xacl);493	saa_writeb(SAA7134_LEVEL_CTRL(task),494		   (vals[i].xc2_1 << 3) | (vals[i].xdcg));495	saa_andorb(SAA7134_FIR_PREFILTER_CTRL(task), 0x0f,496		   (vals[i].vpfy << 2) | vals[i].vpfy);497}498 499static void set_v_scale(struct saa7134_dev *dev, int task, int yscale)500{501	int val,mirror;502 503	saa_writeb(SAA7134_V_SCALE_RATIO1(task), yscale &  0xff);504	saa_writeb(SAA7134_V_SCALE_RATIO2(task), yscale >> 8);505 506	mirror = (dev->ctl_mirror) ? 0x02 : 0x00;507	if (yscale < 2048) {508		/* LPI */509		video_dbg("yscale LPI yscale=%d\n", yscale);510		saa_writeb(SAA7134_V_FILTER(task), 0x00 | mirror);511		saa_writeb(SAA7134_LUMA_CONTRAST(task), 0x40);512		saa_writeb(SAA7134_CHROMA_SATURATION(task), 0x40);513	} else {514		/* ACM */515		val = 0x40 * 1024 / yscale;516		video_dbg("yscale ACM yscale=%d val=0x%x\n", yscale, val);517		saa_writeb(SAA7134_V_FILTER(task), 0x01 | mirror);518		saa_writeb(SAA7134_LUMA_CONTRAST(task), val);519		saa_writeb(SAA7134_CHROMA_SATURATION(task), val);520	}521	saa_writeb(SAA7134_LUMA_BRIGHT(task),       0x80);522}523 524static void set_size(struct saa7134_dev *dev, int task,525		     int width, int height, int interlace)526{527	int prescale,xscale,yscale,y_even,y_odd;528	int h_start, h_stop, v_start, v_stop;529	int div = interlace ? 2 : 1;530 531	/* setup video scaler */532	h_start = dev->crop_current.left;533	v_start = dev->crop_current.top/2;534	h_stop  = (dev->crop_current.left + dev->crop_current.width -1);535	v_stop  = (dev->crop_current.top + dev->crop_current.height -1)/2;536 537	saa_writeb(SAA7134_VIDEO_H_START1(task), h_start &  0xff);538	saa_writeb(SAA7134_VIDEO_H_START2(task), h_start >> 8);539	saa_writeb(SAA7134_VIDEO_H_STOP1(task),  h_stop  &  0xff);540	saa_writeb(SAA7134_VIDEO_H_STOP2(task),  h_stop  >> 8);541	saa_writeb(SAA7134_VIDEO_V_START1(task), v_start &  0xff);542	saa_writeb(SAA7134_VIDEO_V_START2(task), v_start >> 8);543	saa_writeb(SAA7134_VIDEO_V_STOP1(task),  v_stop  &  0xff);544	saa_writeb(SAA7134_VIDEO_V_STOP2(task),  v_stop  >> 8);545 546	prescale = dev->crop_current.width / width;547	if (0 == prescale)548		prescale = 1;549	xscale = 1024 * dev->crop_current.width / prescale / width;550	yscale = 512 * div * dev->crop_current.height / height;551	video_dbg("prescale=%d xscale=%d yscale=%d\n",552		  prescale, xscale, yscale);553	set_h_prescale(dev,task,prescale);554	saa_writeb(SAA7134_H_SCALE_INC1(task),      xscale &  0xff);555	saa_writeb(SAA7134_H_SCALE_INC2(task),      xscale >> 8);556	set_v_scale(dev,task,yscale);557 558	saa_writeb(SAA7134_VIDEO_PIXELS1(task),     width  & 0xff);559	saa_writeb(SAA7134_VIDEO_PIXELS2(task),     width  >> 8);560	saa_writeb(SAA7134_VIDEO_LINES1(task),      height/div & 0xff);561	saa_writeb(SAA7134_VIDEO_LINES2(task),      height/div >> 8);562 563	/* deinterlace y offsets */564	y_odd  = dev->ctl_y_odd;565	y_even = dev->ctl_y_even;566	saa_writeb(SAA7134_V_PHASE_OFFSET0(task), y_odd);567	saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);568	saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);569	saa_writeb(SAA7134_V_PHASE_OFFSET3(task), y_even);570}571 572/* ------------------------------------------------------------------ */573 574/*575 * Media Controller helper functions576 */577 578static int saa7134_enable_analog_tuner(struct saa7134_dev *dev)579{580#ifdef CONFIG_MEDIA_CONTROLLER581	struct media_device *mdev = dev->media_dev;582	struct media_entity *source;583	struct media_link *link, *found_link = NULL;584	int ret, active_links = 0;585 586	if (!mdev || !dev->decoder)587		return 0;588 589	/*590	 * This will find the tuner that is connected into the decoder.591	 * Technically, this is not 100% correct, as the device may be592	 * using an analog input instead of the tuner. However, as we can't593	 * do DVB streaming while the DMA engine is being used for V4L2,594	 * this should be enough for the actual needs.595	 */596	list_for_each_entry(link, &dev->decoder->links, list) {597		if (link->sink->entity == dev->decoder) {598			found_link = link;599			if (link->flags & MEDIA_LNK_FL_ENABLED)600				active_links++;601			break;602		}603	}604 605	if (active_links == 1 || !found_link)606		return 0;607 608	source = found_link->source->entity;609	list_for_each_entry(link, &source->links, list) {610		struct media_entity *sink;611		int flags = 0;612 613		sink = link->sink->entity;614 615		if (sink == dev->decoder)616			flags = MEDIA_LNK_FL_ENABLED;617 618		ret = media_entity_setup_link(link, flags);619		if (ret) {620			pr_err("Couldn't change link %s->%s to %s. Error %d\n",621			       source->name, sink->name,622			       flags ? "enabled" : "disabled",623			       ret);624			return ret;625		}626	}627#endif628	return 0;629}630 631/* ------------------------------------------------------------------ */632 633static int buffer_activate(struct saa7134_dev *dev,634			   struct saa7134_buf *buf,635			   struct saa7134_buf *next)636{637	struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv;638	unsigned long base,control,bpl;639	unsigned long bpl_uv, lines_uv, base2, base3; /* planar */640 641	video_dbg("buffer_activate buf=%p\n", buf);642	buf->top_seen = 0;643 644	set_size(dev, TASK_A, dev->width, dev->height,645		 V4L2_FIELD_HAS_BOTH(dev->field));646	if (dev->fmt->yuv)647		saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x03);648	else649		saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x01);650	saa_writeb(SAA7134_OFMT_VIDEO_A, dev->fmt->pm);651 652	/* DMA: setup channel 0 (= Video Task A0) */653	base  = saa7134_buffer_base(buf);654	if (dev->fmt->planar)655		bpl = dev->width;656	else657		bpl = (dev->width * dev->fmt->depth) / 8;658	control = SAA7134_RS_CONTROL_BURST_16 |659		SAA7134_RS_CONTROL_ME |660		(dmaq->pt.dma >> 12);661	if (dev->fmt->bswap)662		control |= SAA7134_RS_CONTROL_BSWAP;663	if (dev->fmt->wswap)664		control |= SAA7134_RS_CONTROL_WSWAP;665	if (V4L2_FIELD_HAS_BOTH(dev->field)) {666		/* interlaced */667		saa_writel(SAA7134_RS_BA1(0),base);668		saa_writel(SAA7134_RS_BA2(0),base+bpl);669		saa_writel(SAA7134_RS_PITCH(0),bpl*2);670	} else {671		/* non-interlaced */672		saa_writel(SAA7134_RS_BA1(0),base);673		saa_writel(SAA7134_RS_BA2(0),base);674		saa_writel(SAA7134_RS_PITCH(0),bpl);675	}676	saa_writel(SAA7134_RS_CONTROL(0),control);677 678	if (dev->fmt->planar) {679		/* DMA: setup channel 4+5 (= planar task A) */680		bpl_uv   = bpl >> dev->fmt->hshift;681		lines_uv = dev->height >> dev->fmt->vshift;682		base2    = base + bpl * dev->height;683		base3    = base2 + bpl_uv * lines_uv;684		if (dev->fmt->uvswap)685			swap(base2, base3);686		video_dbg("uv: bpl=%ld lines=%ld base2/3=%ld/%ld\n",687			bpl_uv,lines_uv,base2,base3);688		if (V4L2_FIELD_HAS_BOTH(dev->field)) {689			/* interlaced */690			saa_writel(SAA7134_RS_BA1(4),base2);691			saa_writel(SAA7134_RS_BA2(4),base2+bpl_uv);692			saa_writel(SAA7134_RS_PITCH(4),bpl_uv*2);693			saa_writel(SAA7134_RS_BA1(5),base3);694			saa_writel(SAA7134_RS_BA2(5),base3+bpl_uv);695			saa_writel(SAA7134_RS_PITCH(5),bpl_uv*2);696		} else {697			/* non-interlaced */698			saa_writel(SAA7134_RS_BA1(4),base2);699			saa_writel(SAA7134_RS_BA2(4),base2);700			saa_writel(SAA7134_RS_PITCH(4),bpl_uv);701			saa_writel(SAA7134_RS_BA1(5),base3);702			saa_writel(SAA7134_RS_BA2(5),base3);703			saa_writel(SAA7134_RS_PITCH(5),bpl_uv);704		}705		saa_writel(SAA7134_RS_CONTROL(4),control);706		saa_writel(SAA7134_RS_CONTROL(5),control);707	}708 709	/* start DMA */710	saa7134_set_dmabits(dev);711	mod_timer(&dmaq->timeout, jiffies + BUFFER_TIMEOUT);712	return 0;713}714 715static int buffer_init(struct vb2_buffer *vb2)716{717	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;718	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);719	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);720 721	dmaq->curr = NULL;722	buf->activate = buffer_activate;723	return 0;724}725 726static int buffer_prepare(struct vb2_buffer *vb2)727{728	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;729	struct saa7134_dev *dev = dmaq->dev;730	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);731	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);732	struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);733	unsigned int size;734 735	if (dma->sgl->offset) {736		pr_err("The buffer is not page-aligned\n");737		return -EINVAL;738	}739	size = (dev->width * dev->height * dev->fmt->depth) >> 3;740	if (vb2_plane_size(vb2, 0) < size)741		return -EINVAL;742 743	vb2_set_plane_payload(vb2, 0, size);744	vbuf->field = dev->field;745 746	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,747				    saa7134_buffer_startpage(buf));748}749 750static int queue_setup(struct vb2_queue *q,751			   unsigned int *nbuffers, unsigned int *nplanes,752			   unsigned int sizes[], struct device *alloc_devs[])753{754	struct saa7134_dmaqueue *dmaq = q->drv_priv;755	struct saa7134_dev *dev = dmaq->dev;756	int size = dev->fmt->depth * dev->width * dev->height >> 3;757 758	if (dev->width    < 48 ||759	    dev->height   < 32 ||760	    dev->width/4  > dev->crop_current.width  ||761	    dev->height/4 > dev->crop_current.height ||762	    dev->width    > dev->crop_bounds.width  ||763	    dev->height   > dev->crop_bounds.height)764		return -EINVAL;765 766	*nbuffers = saa7134_buffer_count(size, *nbuffers);767	*nplanes = 1;768	sizes[0] = size;769 770	saa7134_enable_analog_tuner(dev);771 772	return 0;773}774 775/*776 * move buffer to hardware queue777 */778void saa7134_vb2_buffer_queue(struct vb2_buffer *vb)779{780	struct saa7134_dmaqueue *dmaq = vb->vb2_queue->drv_priv;781	struct saa7134_dev *dev = dmaq->dev;782	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);783	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);784 785	saa7134_buffer_queue(dev, dmaq, buf);786}787EXPORT_SYMBOL_GPL(saa7134_vb2_buffer_queue);788 789int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)790{791	struct saa7134_dmaqueue *dmaq = vq->drv_priv;792	struct saa7134_dev *dev = dmaq->dev;793 794	/*795	 * Planar video capture and TS share the same DMA channel,796	 * so only one can be active at a time.797	 */798	if (card_is_empress(dev) && vb2_is_busy(&dev->empress_vbq) &&799	    dmaq == &dev->video_q && dev->fmt->planar) {800		struct saa7134_buf *buf, *tmp;801 802		list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {803			list_del(&buf->entry);804			vb2_buffer_done(&buf->vb2.vb2_buf,805					VB2_BUF_STATE_QUEUED);806		}807		if (dmaq->curr) {808			vb2_buffer_done(&dmaq->curr->vb2.vb2_buf,809					VB2_BUF_STATE_QUEUED);810			dmaq->curr = NULL;811		}812		return -EBUSY;813	}814 815	/* The SAA7134 has a 1K FIFO; the datasheet suggests that when816	 * configured conservatively, there's 22 usec of buffering for video.817	 * We therefore request a DMA latency of 20 usec, giving us 2 usec of818	 * margin in case the FIFO is configured differently to the datasheet.819	 * Unfortunately, I lack register-level documentation to check the820	 * Linux FIFO setup and confirm the perfect value.821	 */822	if ((dmaq == &dev->video_q && !vb2_is_streaming(&dev->vbi_vbq)) ||823	    (dmaq == &dev->vbi_q && !vb2_is_streaming(&dev->video_vbq)))824		cpu_latency_qos_add_request(&dev->qos_request, 20);825	dmaq->seq_nr = 0;826 827	return 0;828}829 830void saa7134_vb2_stop_streaming(struct vb2_queue *vq)831{832	struct saa7134_dmaqueue *dmaq = vq->drv_priv;833	struct saa7134_dev *dev = dmaq->dev;834 835	saa7134_stop_streaming(dev, dmaq);836 837	if ((dmaq == &dev->video_q && !vb2_is_streaming(&dev->vbi_vbq)) ||838	    (dmaq == &dev->vbi_q && !vb2_is_streaming(&dev->video_vbq)))839		cpu_latency_qos_remove_request(&dev->qos_request);840}841 842static const struct vb2_ops vb2_qops = {843	.queue_setup	= queue_setup,844	.buf_init	= buffer_init,845	.buf_prepare	= buffer_prepare,846	.buf_queue	= saa7134_vb2_buffer_queue,847	.wait_prepare	= vb2_ops_wait_prepare,848	.wait_finish	= vb2_ops_wait_finish,849	.start_streaming = saa7134_vb2_start_streaming,850	.stop_streaming = saa7134_vb2_stop_streaming,851};852 853/* ------------------------------------------------------------------ */854 855static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl)856{857	struct saa7134_dev *dev = container_of(ctrl->handler, struct saa7134_dev, ctrl_handler);858 859	switch (ctrl->id) {860	case V4L2_CID_BRIGHTNESS:861		dev->ctl_bright = ctrl->val;862		saa_writeb(SAA7134_DEC_LUMA_BRIGHT, ctrl->val);863		break;864	case V4L2_CID_HUE:865		dev->ctl_hue = ctrl->val;866		saa_writeb(SAA7134_DEC_CHROMA_HUE, ctrl->val);867		break;868	case V4L2_CID_CONTRAST:869		dev->ctl_contrast = ctrl->val;870		saa_writeb(SAA7134_DEC_LUMA_CONTRAST,871			   dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);872		break;873	case V4L2_CID_SATURATION:874		dev->ctl_saturation = ctrl->val;875		saa_writeb(SAA7134_DEC_CHROMA_SATURATION,876			   dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);877		break;878	case V4L2_CID_AUDIO_MUTE:879		dev->ctl_mute = ctrl->val;880		saa7134_tvaudio_setmute(dev);881		break;882	case V4L2_CID_AUDIO_VOLUME:883		dev->ctl_volume = ctrl->val;884		saa7134_tvaudio_setvolume(dev,dev->ctl_volume);885		break;886	case V4L2_CID_PRIVATE_INVERT:887		dev->ctl_invert = ctrl->val;888		saa_writeb(SAA7134_DEC_LUMA_CONTRAST,889			   dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);890		saa_writeb(SAA7134_DEC_CHROMA_SATURATION,891			   dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);892		break;893	case V4L2_CID_HFLIP:894		dev->ctl_mirror = ctrl->val;895		break;896	case V4L2_CID_PRIVATE_Y_EVEN:897		dev->ctl_y_even = ctrl->val;898		break;899	case V4L2_CID_PRIVATE_Y_ODD:900		dev->ctl_y_odd = ctrl->val;901		break;902	case V4L2_CID_PRIVATE_AUTOMUTE:903	{904		struct v4l2_priv_tun_config tda9887_cfg;905 906		tda9887_cfg.tuner = TUNER_TDA9887;907		tda9887_cfg.priv = &dev->tda9887_conf;908 909		dev->ctl_automute = ctrl->val;910		if (dev->tda9887_conf) {911			if (dev->ctl_automute)912				dev->tda9887_conf |= TDA9887_AUTOMUTE;913			else914				dev->tda9887_conf &= ~TDA9887_AUTOMUTE;915 916			saa_call_all(dev, tuner, s_config, &tda9887_cfg);917		}918		break;919	}920	default:921		return -EINVAL;922	}923	return 0;924}925 926/* ------------------------------------------------------------------ */927 928static int video_open(struct file *file)929{930	struct video_device *vdev = video_devdata(file);931	struct saa7134_dev *dev = video_drvdata(file);932	int ret = v4l2_fh_open(file);933 934	if (ret < 0)935		return ret;936 937	mutex_lock(&dev->lock);938	if (vdev->vfl_type == VFL_TYPE_RADIO) {939		/* switch to radio mode */940		saa7134_tvaudio_setinput(dev, &card(dev).radio);941		saa_call_all(dev, tuner, s_radio);942	} else {943		/* switch to video/vbi mode */944		video_mux(dev, dev->ctl_input);945	}946	mutex_unlock(&dev->lock);947 948	return 0;949}950 951static int video_release(struct file *file)952{953	struct video_device *vdev = video_devdata(file);954	struct saa7134_dev *dev = video_drvdata(file);955	struct saa6588_command cmd;956 957	mutex_lock(&dev->lock);958	saa7134_tvaudio_close(dev);959 960	if (vdev->vfl_type == VFL_TYPE_RADIO)961		v4l2_fh_release(file);962	else963		_vb2_fop_release(file, NULL);964 965	/* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/966	saa_andorb(SAA7134_OFMT_VIDEO_A, 0x1f, 0);967	saa_andorb(SAA7134_OFMT_VIDEO_B, 0x1f, 0);968	saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);969	saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);970 971	saa_call_all(dev, tuner, standby);972	if (vdev->vfl_type == VFL_TYPE_RADIO)973		saa_call_all(dev, core, command, SAA6588_CMD_CLOSE, &cmd);974	mutex_unlock(&dev->lock);975 976	return 0;977}978 979static ssize_t radio_read(struct file *file, char __user *data,980			 size_t count, loff_t *ppos)981{982	struct saa7134_dev *dev = video_drvdata(file);983	struct saa6588_command cmd;984 985	cmd.block_count = count/3;986	cmd.nonblocking = file->f_flags & O_NONBLOCK;987	cmd.buffer = data;988	cmd.instance = file;989	cmd.result = -ENODEV;990 991	mutex_lock(&dev->lock);992	saa_call_all(dev, core, command, SAA6588_CMD_READ, &cmd);993	mutex_unlock(&dev->lock);994 995	return cmd.result;996}997 998static __poll_t radio_poll(struct file *file, poll_table *wait)999{1000	struct saa7134_dev *dev = video_drvdata(file);1001	struct saa6588_command cmd;1002	__poll_t rc = v4l2_ctrl_poll(file, wait);1003 1004	cmd.instance = file;1005	cmd.event_list = wait;1006	cmd.poll_mask = 0;1007	mutex_lock(&dev->lock);1008	saa_call_all(dev, core, command, SAA6588_CMD_POLL, &cmd);1009	mutex_unlock(&dev->lock);1010 1011	return rc | cmd.poll_mask;1012}1013 1014/* ------------------------------------------------------------------ */1015 1016static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,1017						struct v4l2_format *f)1018{1019	struct saa7134_dev *dev = video_drvdata(file);1020	struct saa7134_tvnorm *norm = dev->tvnorm;1021 1022	memset(&f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));1023	f->fmt.vbi.sampling_rate = 6750000 * 4;1024	f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;1025	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;1026	f->fmt.vbi.offset = 64 * 4;1027	f->fmt.vbi.start[0] = norm->vbi_v_start_0;1028	f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;1029	f->fmt.vbi.start[1] = norm->vbi_v_start_1;1030	f->fmt.vbi.count[1] = f->fmt.vbi.count[0];1031	f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */1032 1033	return 0;1034}1035 1036static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,1037				struct v4l2_format *f)1038{1039	struct saa7134_dev *dev = video_drvdata(file);1040 1041	f->fmt.pix.width        = dev->width;1042	f->fmt.pix.height       = dev->height;1043	f->fmt.pix.field        = dev->field;1044	f->fmt.pix.pixelformat  = dev->fmt->fourcc;1045	if (dev->fmt->planar)1046		f->fmt.pix.bytesperline = f->fmt.pix.width;1047	else1048		f->fmt.pix.bytesperline =1049			(f->fmt.pix.width * dev->fmt->depth) / 8;1050	f->fmt.pix.sizeimage =1051		(f->fmt.pix.height * f->fmt.pix.width * dev->fmt->depth) / 8;1052	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;1053	return 0;1054}1055 1056static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,1057						struct v4l2_format *f)1058{1059	struct saa7134_dev *dev = video_drvdata(file);1060	struct saa7134_format *fmt;1061	enum v4l2_field field;1062	unsigned int maxw, maxh;1063 1064	fmt = format_by_fourcc(f->fmt.pix.pixelformat);1065	if (NULL == fmt)1066		return -EINVAL;1067 1068	field = f->fmt.pix.field;1069	maxw  = min(dev->crop_current.width*4,  dev->crop_bounds.width);1070	maxh  = min(dev->crop_current.height*4, dev->crop_bounds.height);1071 1072	if (V4L2_FIELD_ANY == field) {1073		field = (f->fmt.pix.height > maxh/2)1074			? V4L2_FIELD_INTERLACED1075			: V4L2_FIELD_BOTTOM;1076	}1077	switch (field) {1078	case V4L2_FIELD_TOP:1079	case V4L2_FIELD_BOTTOM:1080		maxh = maxh / 2;1081		break;1082	default:1083		field = V4L2_FIELD_INTERLACED;1084		break;1085	}1086 1087	f->fmt.pix.field = field;1088	if (f->fmt.pix.width  < 48)1089		f->fmt.pix.width  = 48;1090	if (f->fmt.pix.height < 32)1091		f->fmt.pix.height = 32;1092	if (f->fmt.pix.width > maxw)1093		f->fmt.pix.width = maxw;1094	if (f->fmt.pix.height > maxh)1095		f->fmt.pix.height = maxh;1096	f->fmt.pix.width &= ~0x03;1097	if (fmt->planar)1098		f->fmt.pix.bytesperline = f->fmt.pix.width;1099	else1100		f->fmt.pix.bytesperline =1101			(f->fmt.pix.width * fmt->depth) / 8;1102	f->fmt.pix.sizeimage =1103		(f->fmt.pix.height * f->fmt.pix.width * fmt->depth) / 8;1104	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;1105 1106	return 0;1107}1108 1109static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,1110					struct v4l2_format *f)1111{1112	struct saa7134_dev *dev = video_drvdata(file);1113	int err;1114 1115	err = saa7134_try_fmt_vid_cap(file, priv, f);1116	if (0 != err)1117		return err;1118 1119	dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);1120	dev->width = f->fmt.pix.width;1121	dev->height = f->fmt.pix.height;1122	dev->field = f->fmt.pix.field;1123	return 0;1124}1125 1126int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i)1127{1128	struct saa7134_dev *dev = video_drvdata(file);1129	unsigned int n;1130 1131	n = i->index;1132	if (n >= SAA7134_INPUT_MAX)1133		return -EINVAL;1134	if (card_in(dev, i->index).type == SAA7134_NO_INPUT)1135		return -EINVAL;1136	i->index = n;1137	strscpy(i->name, saa7134_input_name[card_in(dev, n).type],1138		sizeof(i->name));1139	switch (card_in(dev, n).type) {1140	case SAA7134_INPUT_TV:1141	case SAA7134_INPUT_TV_MONO:1142		i->type = V4L2_INPUT_TYPE_TUNER;1143		break;1144	default:1145		i->type  = V4L2_INPUT_TYPE_CAMERA;1146		break;1147	}1148	if (n == dev->ctl_input) {1149		int v1 = saa_readb(SAA7134_STATUS_VIDEO1);1150		int v2 = saa_readb(SAA7134_STATUS_VIDEO2);1151 1152		if (0 != (v1 & 0x40))1153			i->status |= V4L2_IN_ST_NO_H_LOCK;1154		if (0 != (v2 & 0x40))1155			i->status |= V4L2_IN_ST_NO_SIGNAL;1156		if (0 != (v2 & 0x0e))1157			i->status |= V4L2_IN_ST_MACROVISION;1158	}1159	i->std = SAA7134_NORMS;1160	return 0;1161}1162EXPORT_SYMBOL_GPL(saa7134_enum_input);1163 1164int saa7134_g_input(struct file *file, void *priv, unsigned int *i)1165{1166	struct saa7134_dev *dev = video_drvdata(file);1167 1168	*i = dev->ctl_input;1169	return 0;1170}1171EXPORT_SYMBOL_GPL(saa7134_g_input);1172 1173int saa7134_s_input(struct file *file, void *priv, unsigned int i)1174{1175	struct saa7134_dev *dev = video_drvdata(file);1176 1177	if (i >= SAA7134_INPUT_MAX)1178		return -EINVAL;1179	if (card_in(dev, i).type == SAA7134_NO_INPUT)1180		return -EINVAL;1181	video_mux(dev, i);1182	return 0;1183}1184EXPORT_SYMBOL_GPL(saa7134_s_input);1185 1186int saa7134_querycap(struct file *file, void *priv,1187					struct v4l2_capability *cap)1188{1189	struct saa7134_dev *dev = video_drvdata(file);1190 1191	strscpy(cap->driver, "saa7134", sizeof(cap->driver));1192	strscpy(cap->card, saa7134_boards[dev->board].name,1193		sizeof(cap->card));1194	cap->capabilities = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |1195			    V4L2_CAP_RADIO | V4L2_CAP_VIDEO_CAPTURE |1196			    V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS;1197	if (dev->tuner_type != TUNER_ABSENT && dev->tuner_type != UNSET)1198		cap->capabilities |= V4L2_CAP_TUNER;1199	if (dev->has_rds)1200		cap->capabilities |= V4L2_CAP_RDS_CAPTURE;1201 1202	return 0;1203}1204EXPORT_SYMBOL_GPL(saa7134_querycap);1205 1206int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)1207{1208	struct saa7134_dev *dev = video_drvdata(file);1209	unsigned int i;1210	v4l2_std_id fixup;1211 1212	for (i = 0; i < TVNORMS; i++)1213		if (id == tvnorms[i].id)1214			break;1215 1216	if (i == TVNORMS)1217		for (i = 0; i < TVNORMS; i++)1218			if (id & tvnorms[i].id)1219				break;1220	if (i == TVNORMS)1221		return -EINVAL;1222 1223	if ((id & V4L2_STD_SECAM) && (secam[0] != '-')) {1224		if (secam[0] == 'L' || secam[0] == 'l') {1225			if (secam[1] == 'C' || secam[1] == 'c')1226				fixup = V4L2_STD_SECAM_LC;1227			else1228				fixup = V4L2_STD_SECAM_L;1229		} else {1230			if (secam[0] == 'D' || secam[0] == 'd')1231				fixup = V4L2_STD_SECAM_DK;1232			else1233				fixup = V4L2_STD_SECAM;1234		}1235		for (i = 0; i < TVNORMS; i++) {1236			if (fixup == tvnorms[i].id)1237				break;1238		}1239		if (i == TVNORMS)1240			return -EINVAL;1241	}1242 1243	set_tvnorm(dev, &tvnorms[i]);1244 1245	saa7134_tvaudio_do_scan(dev);1246	return 0;1247}1248EXPORT_SYMBOL_GPL(saa7134_s_std);1249 1250int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)1251{1252	struct saa7134_dev *dev = video_drvdata(file);1253 1254	*id = dev->tvnorm->id;1255	return 0;1256}1257EXPORT_SYMBOL_GPL(saa7134_g_std);1258 1259static v4l2_std_id saa7134_read_std(struct saa7134_dev *dev)1260{1261	static v4l2_std_id stds[] = {1262		V4L2_STD_UNKNOWN,1263		V4L2_STD_NTSC,1264		V4L2_STD_PAL,1265		V4L2_STD_SECAM };1266 1267	v4l2_std_id result = 0;1268 1269	u8 st1 = saa_readb(SAA7134_STATUS_VIDEO1);1270	u8 st2 = saa_readb(SAA7134_STATUS_VIDEO2);1271 1272	if (!(st2 & 0x1)) /* RDCAP == 0 */1273		result = V4L2_STD_UNKNOWN;1274	else1275		result = stds[st1 & 0x03];1276 1277	return result;1278}1279 1280int saa7134_querystd(struct file *file, void *priv, v4l2_std_id *std)1281{1282	struct saa7134_dev *dev = video_drvdata(file);1283	*std &= saa7134_read_std(dev);1284	return 0;1285}1286EXPORT_SYMBOL_GPL(saa7134_querystd);1287 1288static int saa7134_g_pixelaspect(struct file *file, void *priv,1289				 int type, struct v4l2_fract *f)1290{1291	struct saa7134_dev *dev = video_drvdata(file);1292 1293	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1294		return -EINVAL;1295 1296	if (dev->tvnorm->id & V4L2_STD_525_60) {1297		f->numerator   = 11;1298		f->denominator = 10;1299	}1300	if (dev->tvnorm->id & V4L2_STD_625_50) {1301		f->numerator   = 54;1302		f->denominator = 59;1303	}1304	return 0;1305}1306 1307static int saa7134_g_selection(struct file *file, void *f, struct v4l2_selection *sel)1308{1309	struct saa7134_dev *dev = video_drvdata(file);1310 1311	if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1312		return -EINVAL;1313 1314	switch (sel->target) {1315	case V4L2_SEL_TGT_CROP:1316		sel->r = dev->crop_current;1317		break;1318	case V4L2_SEL_TGT_CROP_DEFAULT:1319		sel->r = dev->crop_defrect;1320		break;1321	case V4L2_SEL_TGT_CROP_BOUNDS:1322		sel->r  = dev->crop_bounds;1323		break;1324	default:1325		return -EINVAL;1326	}1327	return 0;1328}1329 1330static int saa7134_s_selection(struct file *file, void *f, struct v4l2_selection *sel)1331{1332	struct saa7134_dev *dev = video_drvdata(file);1333	struct v4l2_rect *b = &dev->crop_bounds;1334	struct v4l2_rect *c = &dev->crop_current;1335 1336	if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1337		return -EINVAL;1338 1339	if (sel->target != V4L2_SEL_TGT_CROP)1340		return -EINVAL;1341 1342	if (vb2_is_streaming(&dev->video_vbq))1343		return -EBUSY;1344 1345	*c = sel->r;1346	if (c->top < b->top)1347		c->top = b->top;1348	if (c->top > b->top + b->height)1349		c->top = b->top + b->height;1350	if (c->height > b->top - c->top + b->height)1351		c->height = b->top - c->top + b->height;1352 1353	if (c->left < b->left)1354		c->left = b->left;1355	if (c->left > b->left + b->width)1356		c->left = b->left + b->width;1357	if (c->width > b->left - c->left + b->width)1358		c->width = b->left - c->left + b->width;1359	sel->r = *c;1360	return 0;1361}1362 1363int saa7134_g_tuner(struct file *file, void *priv,1364					struct v4l2_tuner *t)1365{1366	struct saa7134_dev *dev = video_drvdata(file);1367	int n;1368 1369	if (0 != t->index)1370		return -EINVAL;1371	memset(t, 0, sizeof(*t));1372	for (n = 0; n < SAA7134_INPUT_MAX; n++) {1373		if (card_in(dev, n).type == SAA7134_INPUT_TV ||1374		    card_in(dev, n).type == SAA7134_INPUT_TV_MONO)1375			break;1376	}1377	if (n == SAA7134_INPUT_MAX)1378		return -EINVAL;1379	if (card_in(dev, n).type != SAA7134_NO_INPUT) {1380		strscpy(t->name, "Television", sizeof(t->name));1381		t->type = V4L2_TUNER_ANALOG_TV;1382		saa_call_all(dev, tuner, g_tuner, t);1383		t->capability = V4L2_TUNER_CAP_NORM |1384			V4L2_TUNER_CAP_STEREO |1385			V4L2_TUNER_CAP_LANG1 |1386			V4L2_TUNER_CAP_LANG2;1387		t->rxsubchans = saa7134_tvaudio_getstereo(dev);1388		t->audmode = saa7134_tvaudio_rx2mode(t->rxsubchans);1389	}1390	if (0 != (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03))1391		t->signal = 0xffff;1392	return 0;1393}1394EXPORT_SYMBOL_GPL(saa7134_g_tuner);1395 1396int saa7134_s_tuner(struct file *file, void *priv,1397					const struct v4l2_tuner *t)1398{1399	struct saa7134_dev *dev = video_drvdata(file);1400	int rx, mode;1401 1402	if (0 != t->index)1403		return -EINVAL;1404 1405	mode = dev->thread.mode;1406	if (UNSET == mode) {1407		rx   = saa7134_tvaudio_getstereo(dev);1408		mode = saa7134_tvaudio_rx2mode(rx);1409	}1410	if (mode != t->audmode)1411		dev->thread.mode = t->audmode;1412 1413	return 0;1414}1415EXPORT_SYMBOL_GPL(saa7134_s_tuner);1416 1417int saa7134_g_frequency(struct file *file, void *priv,1418					struct v4l2_frequency *f)1419{1420	struct saa7134_dev *dev = video_drvdata(file);1421 1422	if (0 != f->tuner)1423		return -EINVAL;1424 1425	saa_call_all(dev, tuner, g_frequency, f);1426 1427	return 0;1428}1429EXPORT_SYMBOL_GPL(saa7134_g_frequency);1430 1431int saa7134_s_frequency(struct file *file, void *priv,1432					const struct v4l2_frequency *f)1433{1434	struct saa7134_dev *dev = video_drvdata(file);1435 1436	if (0 != f->tuner)1437		return -EINVAL;1438 1439	saa_call_all(dev, tuner, s_frequency, f);1440 1441	saa7134_tvaudio_do_scan(dev);1442	return 0;1443}1444EXPORT_SYMBOL_GPL(saa7134_s_frequency);1445 1446static int saa7134_enum_fmt_vid_cap(struct file *file, void  *priv,1447					struct v4l2_fmtdesc *f)1448{1449	if (f->index >= FORMATS)1450		return -EINVAL;1451 1452	f->pixelformat = formats[f->index].fourcc;1453 1454	return 0;1455}1456 1457#ifdef CONFIG_VIDEO_ADV_DEBUG1458static int vidioc_g_register (struct file *file, void *priv,1459			      struct v4l2_dbg_register *reg)1460{1461	struct saa7134_dev *dev = video_drvdata(file);1462 1463	reg->val = saa_readb(reg->reg & 0xffffff);1464	reg->size = 1;1465	return 0;1466}1467 1468static int vidioc_s_register (struct file *file, void *priv,1469				const struct v4l2_dbg_register *reg)1470{1471	struct saa7134_dev *dev = video_drvdata(file);1472 1473	saa_writeb(reg->reg & 0xffffff, reg->val);1474	return 0;1475}1476#endif1477 1478static int radio_g_tuner(struct file *file, void *priv,1479					struct v4l2_tuner *t)1480{1481	struct saa7134_dev *dev = video_drvdata(file);1482 1483	if (0 != t->index)1484		return -EINVAL;1485 1486	strscpy(t->name, "Radio", sizeof(t->name));1487 1488	saa_call_all(dev, tuner, g_tuner, t);1489	t->audmode &= V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO;1490	if (dev->input->amux == TV) {1491		t->signal = 0xf800 - ((saa_readb(0x581) & 0x1f) << 11);1492		t->rxsubchans = (saa_readb(0x529) & 0x08) ?1493				V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;1494	}1495	return 0;1496}1497static int radio_s_tuner(struct file *file, void *priv,1498					const struct v4l2_tuner *t)1499{1500	struct saa7134_dev *dev = video_drvdata(file);1501 1502	if (0 != t->index)1503		return -EINVAL;1504 1505	saa_call_all(dev, tuner, s_tuner, t);1506	return 0;1507}1508 1509static const struct v4l2_file_operations video_fops =1510{1511	.owner	  = THIS_MODULE,1512	.open	  = video_open,1513	.release  = video_release,1514	.read	  = vb2_fop_read,1515	.poll     = vb2_fop_poll,1516	.mmap	  = vb2_fop_mmap,1517	.unlocked_ioctl	  = video_ioctl2,1518};1519 1520static const struct v4l2_ioctl_ops video_ioctl_ops = {1521	.vidioc_querycap		= saa7134_querycap,1522	.vidioc_enum_fmt_vid_cap	= saa7134_enum_fmt_vid_cap,1523	.vidioc_g_fmt_vid_cap		= saa7134_g_fmt_vid_cap,1524	.vidioc_try_fmt_vid_cap		= saa7134_try_fmt_vid_cap,1525	.vidioc_s_fmt_vid_cap		= saa7134_s_fmt_vid_cap,1526	.vidioc_g_fmt_vbi_cap		= saa7134_try_get_set_fmt_vbi_cap,1527	.vidioc_try_fmt_vbi_cap		= saa7134_try_get_set_fmt_vbi_cap,1528	.vidioc_s_fmt_vbi_cap		= saa7134_try_get_set_fmt_vbi_cap,1529	.vidioc_g_pixelaspect		= saa7134_g_pixelaspect,1530	.vidioc_reqbufs			= vb2_ioctl_reqbufs,1531	.vidioc_querybuf		= vb2_ioctl_querybuf,1532	.vidioc_qbuf			= vb2_ioctl_qbuf,1533	.vidioc_dqbuf			= vb2_ioctl_dqbuf,1534	.vidioc_expbuf			= vb2_ioctl_expbuf,1535	.vidioc_s_std			= saa7134_s_std,1536	.vidioc_g_std			= saa7134_g_std,1537	.vidioc_querystd		= saa7134_querystd,1538	.vidioc_enum_input		= saa7134_enum_input,1539	.vidioc_g_input			= saa7134_g_input,1540	.vidioc_s_input			= saa7134_s_input,1541	.vidioc_streamon		= vb2_ioctl_streamon,1542	.vidioc_streamoff		= vb2_ioctl_streamoff,1543	.vidioc_g_tuner			= saa7134_g_tuner,1544	.vidioc_s_tuner			= saa7134_s_tuner,1545	.vidioc_g_selection		= saa7134_g_selection,1546	.vidioc_s_selection		= saa7134_s_selection,1547	.vidioc_g_frequency		= saa7134_g_frequency,1548	.vidioc_s_frequency		= saa7134_s_frequency,1549#ifdef CONFIG_VIDEO_ADV_DEBUG1550	.vidioc_g_register              = vidioc_g_register,1551	.vidioc_s_register              = vidioc_s_register,1552#endif1553	.vidioc_log_status		= v4l2_ctrl_log_status,1554	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,1555	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,1556};1557 1558static const struct v4l2_file_operations radio_fops = {1559	.owner	  = THIS_MODULE,1560	.open	  = video_open,1561	.read     = radio_read,1562	.release  = video_release,1563	.unlocked_ioctl	= video_ioctl2,1564	.poll     = radio_poll,1565};1566 1567static const struct v4l2_ioctl_ops radio_ioctl_ops = {1568	.vidioc_querycap	= saa7134_querycap,1569	.vidioc_g_tuner		= radio_g_tuner,1570	.vidioc_s_tuner		= radio_s_tuner,1571	.vidioc_g_frequency	= saa7134_g_frequency,1572	.vidioc_s_frequency	= saa7134_s_frequency,1573	.vidioc_subscribe_event	= v4l2_ctrl_subscribe_event,1574	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,1575};1576 1577/* ----------------------------------------------------------- */1578/* exported stuff                                              */1579 1580struct video_device saa7134_video_template = {1581	.name				= "saa7134-video",1582	.fops				= &video_fops,1583	.ioctl_ops			= &video_ioctl_ops,1584	.tvnorms			= SAA7134_NORMS,1585};1586 1587struct video_device saa7134_radio_template = {1588	.name			= "saa7134-radio",1589	.fops			= &radio_fops,1590	.ioctl_ops		= &radio_ioctl_ops,1591};1592 1593static const struct v4l2_ctrl_ops saa7134_ctrl_ops = {1594	.s_ctrl = saa7134_s_ctrl,1595};1596 1597static const struct v4l2_ctrl_config saa7134_ctrl_invert = {1598	.ops = &saa7134_ctrl_ops,1599	.id = V4L2_CID_PRIVATE_INVERT,1600	.name = "Invert",1601	.type = V4L2_CTRL_TYPE_BOOLEAN,1602	.min = 0,1603	.max = 1,1604	.step = 1,1605};1606 1607static const struct v4l2_ctrl_config saa7134_ctrl_y_odd = {1608	.ops = &saa7134_ctrl_ops,1609	.id = V4L2_CID_PRIVATE_Y_ODD,1610	.name = "Y Offset Odd Field",1611	.type = V4L2_CTRL_TYPE_INTEGER,1612	.min = 0,1613	.max = 128,1614	.step = 1,1615};1616 1617static const struct v4l2_ctrl_config saa7134_ctrl_y_even = {1618	.ops = &saa7134_ctrl_ops,1619	.id = V4L2_CID_PRIVATE_Y_EVEN,1620	.name = "Y Offset Even Field",1621	.type = V4L2_CTRL_TYPE_INTEGER,1622	.min = 0,1623	.max = 128,1624	.step = 1,1625};1626 1627static const struct v4l2_ctrl_config saa7134_ctrl_automute = {1628	.ops = &saa7134_ctrl_ops,1629	.id = V4L2_CID_PRIVATE_AUTOMUTE,1630	.name = "Automute",1631	.type = V4L2_CTRL_TYPE_BOOLEAN,1632	.min = 0,1633	.max = 1,1634	.step = 1,1635	.def = 1,1636};1637 1638int saa7134_video_init1(struct saa7134_dev *dev)1639{1640	struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;1641	struct vb2_queue *q;1642	int ret;1643 1644	/* sanitycheck insmod options */1645	if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)1646		gbuffers = 2;1647	if (gbufsize > gbufsize_max)1648		gbufsize = gbufsize_max;1649	gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;1650 1651	v4l2_ctrl_handler_init(hdl, 11);1652	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,1653			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);1654	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,1655			V4L2_CID_CONTRAST, 0, 127, 1, 68);1656	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,1657			V4L2_CID_SATURATION, 0, 127, 1, 64);1658	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,1659			V4L2_CID_HUE, -128, 127, 1, 0);1660	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,1661			V4L2_CID_HFLIP, 0, 1, 1, 0);1662	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,1663			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);1664	v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,1665			V4L2_CID_AUDIO_VOLUME, -15, 15, 1, 0);1666	v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_invert, NULL);1667	v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_y_odd, NULL);1668	v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_y_even, NULL);1669	v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_automute, NULL);1670	if (hdl->error)1671		return hdl->error;1672	if (card_has_radio(dev)) {1673		hdl = &dev->radio_ctrl_handler;1674		v4l2_ctrl_handler_init(hdl, 2);1675		v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler,1676				v4l2_ctrl_radio_filter, false);1677		if (hdl->error)1678			return hdl->error;1679	}1680	dev->ctl_mute       = 1;1681 1682	if (dev->tda9887_conf && saa7134_ctrl_automute.def)1683		dev->tda9887_conf |= TDA9887_AUTOMUTE;1684	dev->automute       = 0;1685 1686	INIT_LIST_HEAD(&dev->video_q.queue);1687	timer_setup(&dev->video_q.timeout, saa7134_buffer_timeout, 0);1688	dev->video_q.dev              = dev;1689	dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);1690	dev->width    = 720;1691	dev->height   = 576;1692	dev->field = V4L2_FIELD_INTERLACED;1693 1694	if (saa7134_boards[dev->board].video_out)1695		saa7134_videoport_init(dev);1696 1697	q = &dev->video_vbq;1698	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;1699	/*1700	 * Do not add VB2_USERPTR unless explicitly requested: the saa7134 DMA1701	 * engine cannot handle transfers that do not start at the beginning1702	 * of a page. A user-provided pointer can start anywhere in a page, so1703	 * USERPTR support is a no-go unless the application knows about these1704	 * limitations and has special support for this.1705	 */1706	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;1707	if (saa7134_userptr)1708		q->io_modes |= VB2_USERPTR;1709	q->drv_priv = &dev->video_q;1710	q->ops = &vb2_qops;1711	q->gfp_flags = GFP_DMA32;1712	q->mem_ops = &vb2_dma_sg_memops;1713	q->buf_struct_size = sizeof(struct saa7134_buf);1714	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;1715	q->lock = &dev->lock;1716	q->dev = &dev->pci->dev;1717	ret = vb2_queue_init(q);1718	if (ret)1719		return ret;1720	saa7134_pgtable_alloc(dev->pci, &dev->video_q.pt);1721 1722	q = &dev->vbi_vbq;1723	q->type = V4L2_BUF_TYPE_VBI_CAPTURE;1724	/* Don't add VB2_USERPTR, see comment above */1725	q->io_modes = VB2_MMAP | VB2_READ;1726	if (saa7134_userptr)1727		q->io_modes |= VB2_USERPTR;1728	q->drv_priv = &dev->vbi_q;1729	q->ops = &saa7134_vbi_qops;1730	q->gfp_flags = GFP_DMA32;1731	q->mem_ops = &vb2_dma_sg_memops;1732	q->buf_struct_size = sizeof(struct saa7134_buf);1733	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;1734	q->lock = &dev->lock;1735	q->dev = &dev->pci->dev;1736	ret = vb2_queue_init(q);1737	if (ret)1738		return ret;1739	saa7134_pgtable_alloc(dev->pci, &dev->vbi_q.pt);1740 1741	return 0;1742}1743 1744void saa7134_video_fini(struct saa7134_dev *dev)1745{1746	del_timer_sync(&dev->video_q.timeout);1747	/* free stuff */1748	saa7134_pgtable_free(dev->pci, &dev->video_q.pt);1749	saa7134_pgtable_free(dev->pci, &dev->vbi_q.pt);1750	v4l2_ctrl_handler_free(&dev->ctrl_handler);1751	if (card_has_radio(dev))1752		v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);1753}1754 1755int saa7134_videoport_init(struct saa7134_dev *dev)1756{1757	/* enable video output */1758	int vo = saa7134_boards[dev->board].video_out;1759	int video_reg;1760	unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts;1761 1762	/* Configure videoport */1763	saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]);1764	video_reg = video_out[vo][1];1765	if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED)1766		video_reg &= ~VP_T_CODE_P_INVERTED;1767	saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg);1768	saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]);1769	saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]);1770	video_reg = video_out[vo][5];1771	if (vid_port_opts & SET_CLOCK_NOT_DELAYED)1772		video_reg &= ~VP_CLK_CTRL2_DELAYED;1773	if (vid_port_opts & SET_CLOCK_INVERTED)1774		video_reg |= VP_CLK_CTRL1_INVERTED;1775	saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg);1776	video_reg = video_out[vo][6];1777	if (vid_port_opts & SET_VSYNC_OFF) {1778		video_reg &= ~VP_VS_TYPE_MASK;1779		video_reg |= VP_VS_TYPE_OFF;1780	}1781	saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg);1782	saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]);1783	saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]);1784 1785	/* Start videoport */1786	saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);1787 1788	return 0;1789}1790 1791int saa7134_video_init2(struct saa7134_dev *dev)1792{1793	/* init video hw */1794	set_tvnorm(dev,&tvnorms[0]);1795	video_mux(dev,0);1796	v4l2_ctrl_handler_setup(&dev->ctrl_handler);1797	saa7134_tvaudio_setmute(dev);1798	saa7134_tvaudio_setvolume(dev,dev->ctl_volume);1799	return 0;1800}1801 1802void saa7134_irq_video_signalchange(struct saa7134_dev *dev)1803{1804	static const char *st[] = {1805		"(no signal)", "NTSC", "PAL", "SECAM" };1806	u32 st1,st2;1807 1808	st1 = saa_readb(SAA7134_STATUS_VIDEO1);1809	st2 = saa_readb(SAA7134_STATUS_VIDEO2);1810	video_dbg("DCSDT: pll: %s, sync: %s, norm: %s\n",1811		(st1 & 0x40) ? "not locked" : "locked",1812		(st2 & 0x40) ? "no"         : "yes",1813		st[st1 & 0x03]);1814	dev->nosignal = (st1 & 0x40) || (st2 & 0x40)  || !(st2 & 0x1);1815 1816	if (dev->nosignal) {1817		/* no video signal -> mute audio */1818		if (dev->ctl_automute)1819			dev->automute = 1;1820		saa7134_tvaudio_setmute(dev);1821	} else {1822		/* wake up tvaudio audio carrier scan thread */1823		saa7134_tvaudio_do_scan(dev);1824	}1825 1826	if ((st2 & 0x80) && !noninterlaced && !dev->nosignal)1827		saa_clearb(SAA7134_SYNC_CTRL, 0x20);1828	else1829		saa_setb(SAA7134_SYNC_CTRL, 0x20);1830 1831	if (dev->mops && dev->mops->signal_change)1832		dev->mops->signal_change(dev);1833}1834 1835 1836void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)1837{1838	enum v4l2_field field;1839 1840	spin_lock(&dev->slock);1841	if (dev->video_q.curr) {1842		field = dev->field;1843		if (V4L2_FIELD_HAS_BOTH(field)) {1844			/* make sure we have seen both fields */1845			if ((status & 0x10) == 0x00) {1846				dev->video_q.curr->top_seen = 1;1847				goto done;1848			}1849			if (!dev->video_q.curr->top_seen)1850				goto done;1851		} else if (field == V4L2_FIELD_TOP) {1852			if ((status & 0x10) != 0x10)1853				goto done;1854		} else if (field == V4L2_FIELD_BOTTOM) {1855			if ((status & 0x10) != 0x00)1856				goto done;1857		}1858		saa7134_buffer_finish(dev, &dev->video_q, VB2_BUF_STATE_DONE);1859	}1860	saa7134_buffer_next(dev, &dev->video_q);1861 1862 done:1863	spin_unlock(&dev->slock);1864}1865