bttv-driver.c

来自「trident tm5600的linux驱动」· C语言 代码 · 共 2,443 行 · 第 1/5 页

C
2,443
字号
static const struct bttv_format formats[] = {	{		.name     = "8 bpp, gray",		.fourcc   = V4L2_PIX_FMT_GREY,		.btformat = BT848_COLOR_FMT_Y8,		.depth    = 8,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "8 bpp, dithered color",		.fourcc   = V4L2_PIX_FMT_HI240,		.btformat = BT848_COLOR_FMT_RGB8,		.depth    = 8,		.flags    = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,	},{		.name     = "15 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_RGB555,		.btformat = BT848_COLOR_FMT_RGB15,		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "15 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB555X,		.btformat = BT848_COLOR_FMT_RGB15,		.btswap   = 0x03, /* byteswap */		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "16 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_RGB565,		.btformat = BT848_COLOR_FMT_RGB16,		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "16 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB565X,		.btformat = BT848_COLOR_FMT_RGB16,		.btswap   = 0x03, /* byteswap */		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "24 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_BGR24,		.btformat = BT848_COLOR_FMT_RGB24,		.depth    = 24,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "32 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_BGR32,		.btformat = BT848_COLOR_FMT_RGB32,		.depth    = 32,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "32 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB32,		.btformat = BT848_COLOR_FMT_RGB32,		.btswap   = 0x0f, /* byte+word swap */		.depth    = 32,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "4:2:2, packed, YUYV",		.fourcc   = V4L2_PIX_FMT_YUYV,		.btformat = BT848_COLOR_FMT_YUY2,		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "4:2:2, packed, YUYV",		.fourcc   = V4L2_PIX_FMT_YUYV,		.btformat = BT848_COLOR_FMT_YUY2,		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "4:2:2, packed, UYVY",		.fourcc   = V4L2_PIX_FMT_UYVY,		.btformat = BT848_COLOR_FMT_YUY2,		.btswap   = 0x03, /* byteswap */		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	},{		.name     = "4:2:2, planar, Y-Cb-Cr",		.fourcc   = V4L2_PIX_FMT_YUV422P,		.btformat = BT848_COLOR_FMT_YCrCb422,		.depth    = 16,		.flags    = FORMAT_FLAGS_PLANAR,		.hshift   = 1,		.vshift   = 0,	},{		.name     = "4:2:0, planar, Y-Cb-Cr",		.fourcc   = V4L2_PIX_FMT_YUV420,		.btformat = BT848_COLOR_FMT_YCrCb422,		.depth    = 12,		.flags    = FORMAT_FLAGS_PLANAR,		.hshift   = 1,		.vshift   = 1,	},{		.name     = "4:2:0, planar, Y-Cr-Cb",		.fourcc   = V4L2_PIX_FMT_YVU420,		.btformat = BT848_COLOR_FMT_YCrCb422,		.depth    = 12,		.flags    = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,		.hshift   = 1,		.vshift   = 1,	},{		.name     = "4:1:1, planar, Y-Cb-Cr",		.fourcc   = V4L2_PIX_FMT_YUV411P,		.btformat = BT848_COLOR_FMT_YCrCb411,		.depth    = 12,		.flags    = FORMAT_FLAGS_PLANAR,		.hshift   = 2,		.vshift   = 0,	},{		.name     = "4:1:0, planar, Y-Cb-Cr",		.fourcc   = V4L2_PIX_FMT_YUV410,		.btformat = BT848_COLOR_FMT_YCrCb411,		.depth    = 9,		.flags    = FORMAT_FLAGS_PLANAR,		.hshift   = 2,		.vshift   = 2,	},{		.name     = "4:1:0, planar, Y-Cr-Cb",		.fourcc   = V4L2_PIX_FMT_YVU410,		.btformat = BT848_COLOR_FMT_YCrCb411,		.depth    = 9,		.flags    = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,		.hshift   = 2,		.vshift   = 2,	},{		.name     = "raw scanlines",		.fourcc   = -1,		.btformat = BT848_COLOR_FMT_RAW,		.depth    = 8,		.flags    = FORMAT_FLAGS_RAW,	}};static const unsigned int FORMATS = ARRAY_SIZE(formats);/* ----------------------------------------------------------------------- */#define V4L2_CID_PRIVATE_CHROMA_AGC  (V4L2_CID_PRIVATE_BASE + 0)#define V4L2_CID_PRIVATE_COMBFILTER  (V4L2_CID_PRIVATE_BASE + 1)#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 2)#define V4L2_CID_PRIVATE_LUMAFILTER  (V4L2_CID_PRIVATE_BASE + 3)#define V4L2_CID_PRIVATE_AGC_CRUSH   (V4L2_CID_PRIVATE_BASE + 4)#define V4L2_CID_PRIVATE_VCR_HACK    (V4L2_CID_PRIVATE_BASE + 5)#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER   (V4L2_CID_PRIVATE_BASE + 6)#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER   (V4L2_CID_PRIVATE_BASE + 7)#define V4L2_CID_PRIVATE_UV_RATIO    (V4L2_CID_PRIVATE_BASE + 8)#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE    (V4L2_CID_PRIVATE_BASE + 9)#define V4L2_CID_PRIVATE_CORING      (V4L2_CID_PRIVATE_BASE + 10)#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 11)static const struct v4l2_queryctrl no_ctl = {	.name  = "42",	.flags = V4L2_CTRL_FLAG_DISABLED,};static const struct v4l2_queryctrl bttv_ctls[] = {	/* --- video --- */	{		.id            = V4L2_CID_BRIGHTNESS,		.name          = "Brightness",		.minimum       = 0,		.maximum       = 65535,		.step          = 256,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_CONTRAST,		.name          = "Contrast",		.minimum       = 0,		.maximum       = 65535,		.step          = 128,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_SATURATION,		.name          = "Saturation",		.minimum       = 0,		.maximum       = 65535,		.step          = 128,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_HUE,		.name          = "Hue",		.minimum       = 0,		.maximum       = 65535,		.step          = 256,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},	/* --- audio --- */	{		.id            = V4L2_CID_AUDIO_MUTE,		.name          = "Mute",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_AUDIO_VOLUME,		.name          = "Volume",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 65535,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_AUDIO_BALANCE,		.name          = "Balance",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_AUDIO_BASS,		.name          = "Bass",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_AUDIO_TREBLE,		.name          = "Treble",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 32768,		.type          = V4L2_CTRL_TYPE_INTEGER,	},	/* --- private --- */	{		.id            = V4L2_CID_PRIVATE_CHROMA_AGC,		.name          = "chroma agc",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_PRIVATE_COMBFILTER,		.name          = "combfilter",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_PRIVATE_AUTOMUTE,		.name          = "automute",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_PRIVATE_LUMAFILTER,		.name          = "luma decimation filter",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_PRIVATE_AGC_CRUSH,		.name          = "agc crush",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_PRIVATE_VCR_HACK,		.name          = "vcr hack",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,		.name          = "whitecrush upper",		.minimum       = 0,		.maximum       = 255,		.step          = 1,		.default_value = 0xCF,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,		.name          = "whitecrush lower",		.minimum       = 0,		.maximum       = 255,		.step          = 1,		.default_value = 0x7F,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_PRIVATE_UV_RATIO,		.name          = "uv ratio",		.minimum       = 0,		.maximum       = 100,		.step          = 1,		.default_value = 50,		.type          = V4L2_CTRL_TYPE_INTEGER,	},{		.id            = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,		.name          = "full luma range",		.minimum       = 0,		.maximum       = 1,		.type          = V4L2_CTRL_TYPE_BOOLEAN,	},{		.id            = V4L2_CID_PRIVATE_CORING,		.name          = "coring",		.minimum       = 0,		.maximum       = 3,		.step          = 1,		.default_value = 0,		.type          = V4L2_CTRL_TYPE_INTEGER,	}};static const struct v4l2_queryctrl *ctrl_by_id(int id){	int i;	for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)		if (bttv_ctls[i].id == id)			return bttv_ctls+i;	return NULL;}/* ----------------------------------------------------------------------- *//* resource management                                                     *//*   RESOURCE_    allocated by                freed by   VIDEO_READ   bttv_read 1)                bttv_read 2)   VIDEO_STREAM VIDIOC_STREAMON             VIDIOC_STREAMOFF		 VIDIOC_QBUF 1)              bttv_release		 VIDIOCMCAPTURE 1)   OVERLAY	 VIDIOCCAPTURE on            VIDIOCCAPTURE off		 VIDIOC_OVERLAY on           VIDIOC_OVERLAY off		 3)                          bttv_release   VBI		 VIDIOC_STREAMON             VIDIOC_STREAMOFF		 VIDIOC_QBUF 1)              bttv_release		 bttv_read, bttv_poll 1) 4)   1) The resource must be allocated when we enter buffer prepare functions      and remain allocated while buffers are in the DMA queue.   2) This is a single frame read.   3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when      RESOURCE_OVERLAY is allocated.   4) This is a continuous read, implies VIDIOC_STREAMON.   Note this driver permits video input and standard changes regardless if   resources are allocated.*/#define VBI_RESOURCES (RESOURCE_VBI)#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \			 RESOURCE_VIDEO_STREAM | \			 RESOURCE_OVERLAY)staticint check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit){	int xbits; /* mutual exclusive resources */	if (fh->resources & bit)		/* have it already allocated */		return 1;	xbits = bit;	if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))		xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;	/* is it free? */	mutex_lock(&btv->lock);	if (btv->resources & xbits) {		/* no, someone else uses it */		goto fail;	}	if ((bit & VIDEO_RESOURCES)	    && 0 == (btv->resources & VIDEO_RESOURCES)) {		/* Do crop - use current, don't - use default parameters. */		__s32 top = btv->crop[!!fh->do_crop].rect.top;		if (btv->vbi_end > top)			goto fail;		/* We cannot capture the same line as video and VBI data.		   Claim scan lines crop[].rect.top to bottom. */		btv->crop_start = top;	} else if (bit & VBI_RESOURCES) {		__s32 end = fh->vbi_fmt.end;		if (end > btv->crop_start)			goto fail;		/* Claim scan lines above fh->vbi_fmt.end. */		btv->vbi_end = end;	}	/* it's free, grab it */	fh->resources  |= bit;	btv->resources |= bit;	mutex_unlock(&btv->lock);	return 1; fail:	mutex_unlock(&btv->lock);	return 0;}staticint check_btres(struct bttv_fh *fh, int bit){	return (fh->resources & bit);}staticint locked_btres(struct bttv *btv, int bit){	return (btv->resources & bit);}/* Call with btv->lock down. */static voiddisclaim_vbi_lines(struct bttv *btv){	btv->vbi_end = 0;}/* Call with btv->lock down. */static voiddisclaim_video_lines(struct bttv *btv){	const struct bttv_tvnorm *tvnorm;	u8 crop;	tvnorm = &bttv_tvnorms[btv->tvnorm];	btv->crop_start = tvnorm->cropcap.bounds.top		+ tvnorm->cropcap.bounds.height;	/* VBI capturing ends at VDELAY, start of video capturing, no	   matter how many lines the VBI RISC program expects. When video	   capturing is off, it shall no longer "preempt" VBI capturing,	   so we set VDELAY to maximum. */	crop = btread(BT848_E_CROP) | 0xc0;	btwrite(crop, BT848_E_CROP);	btwrite(0xfe, BT848_E_VDELAY_LO);	btwrite(crop, BT848_O_CROP);	btwrite(0xfe, BT848_O_VDELAY_LO);}staticvoid free_btres(struct bttv *btv, struct bttv_fh *fh, int bits){#if 1 /* DEBUG */	if ((fh->resources & bits) != bits) {		/* trying to free ressources not allocated by us ... */		printk("bttv: BUG! (btres)\n");	}#endif	mutex_lock(&btv->lock);	fh->resources  &= ~bits;	btv->resources &= ~bits;	bits = btv->resources;	if (0 == (bits & VIDEO_RESOURCES))		disclaim_video_lines(btv);	if (0 == (bits & VBI_RESOURCES))		disclaim_vbi_lines(btv);	mutex_unlock(&btv->lock);}/* ----------------------------------------------------------------------- *//* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC          *//* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C   PLL_X = Reference pre-divider (0=1, 1=2)   PLL_C = Post divider (0=6, 1=4)   PLL_I = Integer input   PLL_F = Fractional input   F_input = 28.636363 MHz:   PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0*/static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout){

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?