⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vivi.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Virtual Video driver - This code emulates a real video device with v4l2 api * * Copyright (c) 2006 by: *      Mauro Carvalho Chehab <mchehab--a.t--infradead.org> *      Ted Walther <ted--a.t--enumera.com> *      John Sokol <sokol--a.t--videotechnology.com> *      http://v4l.videotechnology.com/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the BSD Licence, GNU General Public License * as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version */#include <linux/module.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/pci.h>#include <linux/random.h>#include <linux/version.h>#include <linux/mutex.h>#include "compat.h"#include <linux/videodev2.h>#include <linux/dma-mapping.h>#ifdef CONFIG_VIDEO_V4L1_COMPAT/* Include V4L1 specific functions. Should be removed soon */#include <linux/videodev.h>#endif#include <linux/interrupt.h>#include <media/videobuf-vmalloc.h>#include <media/v4l2-common.h>#include <media/v4l2-ioctl.h>#include <linux/kthread.h>#include <linux/highmem.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)#include <linux/freezer.h>#endif#define VIVI_MODULE_NAME "vivi"/* Wake up at about 30 fps */#define WAKE_NUMERATOR 30#define WAKE_DENOMINATOR 1001#define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */#include "font.h"#define VIVI_MAJOR_VERSION 0#define VIVI_MINOR_VERSION 5#define VIVI_RELEASE 0#define VIVI_VERSION \	KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)/* Declare static vars that will be used as parameters */static unsigned int vid_limit = 16;	/* Video memory limit, in Mb */static int video_nr = -1;		/* /dev/videoN, -1 for autodetect */static int n_devs = 1;			/* Number of virtual devices *//* supported controls */static struct v4l2_queryctrl vivi_qctrl[] = {	{		.id            = V4L2_CID_AUDIO_VOLUME,		.name          = "Volume",		.minimum       = 0,		.maximum       = 65535,		.step          = 65535/100,		.default_value = 65535,		.flags         = 0,		.type          = V4L2_CTRL_TYPE_INTEGER,	}, {		.id            = V4L2_CID_BRIGHTNESS,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Brightness",		.minimum       = 0,		.maximum       = 255,		.step          = 1,		.default_value = 127,		.flags         = 0,	}, {		.id            = V4L2_CID_CONTRAST,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Contrast",		.minimum       = 0,		.maximum       = 255,		.step          = 0x1,		.default_value = 0x10,		.flags         = 0,	}, {		.id            = V4L2_CID_SATURATION,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Saturation",		.minimum       = 0,		.maximum       = 255,		.step          = 0x1,		.default_value = 127,		.flags         = 0,	}, {		.id            = V4L2_CID_HUE,		.type          = V4L2_CTRL_TYPE_INTEGER,		.name          = "Hue",		.minimum       = -128,		.maximum       = 127,		.step          = 0x1,		.default_value = 0,		.flags         = 0,	}};static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];#define dprintk(dev, level, fmt, arg...)				\	do {								\		if (dev->vfd->debug >= (level))				\			printk(KERN_DEBUG "vivi: " fmt , ## arg);	\	} while (0)/* ------------------------------------------------------------------	Basic structures   ------------------------------------------------------------------*/struct vivi_fmt {	char  *name;	u32   fourcc;          /* v4l2 format id */	int   depth;};static struct vivi_fmt formats[] = {	{		.name     = "4:2:2, packed, YUYV",		.fourcc   = V4L2_PIX_FMT_YUYV,		.depth    = 16,	},	{		.name     = "4:2:2, packed, UYVY",		.fourcc   = V4L2_PIX_FMT_UYVY,		.depth    = 16,	},	{		.name     = "RGB565 (LE)",		.fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */		.depth    = 16,	},	{		.name     = "RGB565 (BE)",		.fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */		.depth    = 16,	},	{		.name     = "RGB555 (LE)",		.fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */		.depth    = 16,	},	{		.name     = "RGB555 (BE)",		.fourcc   = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */		.depth    = 16,	},};static struct vivi_fmt *get_format(struct v4l2_format *f){	struct vivi_fmt *fmt;	unsigned int k;	for (k = 0; k < ARRAY_SIZE(formats); k++) {		fmt = &formats[k];		if (fmt->fourcc == f->fmt.pix.pixelformat)			break;	}	if (k == ARRAY_SIZE(formats))		return NULL;	return &formats[k];}struct sg_to_addr {	int pos;	struct scatterlist *sg;};/* buffer for one video frame */struct vivi_buffer {	/* common v4l buffer stuff -- must be first */	struct videobuf_buffer vb;	struct vivi_fmt        *fmt;};struct vivi_dmaqueue {	struct list_head       active;	/* thread for generating video stream*/	struct task_struct         *kthread;	wait_queue_head_t          wq;	/* Counters to control fps rate */	int                        frame;	int                        ini_jiffies;};static LIST_HEAD(vivi_devlist);struct vivi_dev {	struct list_head           vivi_devlist;	spinlock_t                 slock;	struct mutex		   mutex;	int                        users;	/* various device info */	struct video_device        *vfd;	struct vivi_dmaqueue       vidq;	/* Several counters */	int                        h, m, s, ms;	unsigned long              jiffies;	char                       timestr[13];	int			   mv_count;	/* Controls bars movement */};struct vivi_fh {	struct vivi_dev            *dev;	/* video capture */	struct vivi_fmt            *fmt;	unsigned int               width, height;	struct videobuf_queue      vb_vidq;	enum v4l2_buf_type         type;	unsigned char              bars[8][3];};/* ------------------------------------------------------------------	DMA and thread functions   ------------------------------------------------------------------*//* Bars and Colors should match positions */enum colors {	WHITE,	AMBAR,	CYAN,	GREEN,	MAGENTA,	RED,	BLUE,	BLACK,};static u8 bars[8][3] = {	/* R   G   B */	{204, 204, 204},  /* white */	{208, 208,   0},  /* ambar */	{  0, 206, 206},  /* cyan */	{  0, 239,   0},  /* green */	{239,   0, 239},  /* magenta */	{205,   0,   0},  /* red */	{  0,   0, 255},  /* blue */	{  0,   0,   0},  /* black */};#define TO_Y(r, g, b) \	(((16829 * r + 33039 * g + 6416 * b  + 32768) >> 16) + 16)/* RGB to  V(Cr) Color transform */#define TO_V(r, g, b) \	(((28784 * r - 24103 * g - 4681 * b  + 32768) >> 16) + 128)/* RGB to  U(Cb) Color transform */#define TO_U(r, g, b) \	(((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)#define TSTAMP_MIN_Y 24#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15#define TSTAMP_MIN_X 64static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos){	unsigned char r_y, g_u, b_v;	unsigned char *p;	int color;	r_y = fh->bars[colorpos][0]; /* R or precalculated Y */	g_u = fh->bars[colorpos][1]; /* G or precalculated U */	b_v = fh->bars[colorpos][2]; /* B or precalculated V */	for (color = 0; color < 4; color++) {		p = buf + color;		switch (fh->fmt->fourcc) {		case V4L2_PIX_FMT_YUYV:			switch (color) {			case 0:			case 2:				*p = r_y;				break;			case 1:				*p = g_u;				break;			case 3:				*p = b_v;				break;			}			break;		case V4L2_PIX_FMT_UYVY:			switch (color) {			case 1:			case 3:				*p = r_y;				break;			case 0:				*p = g_u;				break;			case 2:				*p = b_v;				break;			}			break;		case V4L2_PIX_FMT_RGB565:			switch (color) {			case 0:			case 2:				*p = (g_u << 5) | b_v;				break;			case 1:			case 3:				*p = (r_y << 3) | (g_u >> 3);				break;			}			break;		case V4L2_PIX_FMT_RGB565X:			switch (color) {			case 0:			case 2:				*p = (r_y << 3) | (g_u >> 3);				break;			case 1:			case 3:				*p = (g_u << 5) | b_v;				break;			}			break;		case V4L2_PIX_FMT_RGB555:			switch (color) {			case 0:			case 2:				*p = (g_u << 5) | b_v;				break;			case 1:			case 3:				*p = (r_y << 2) | (g_u >> 3);				break;			}			break;		case V4L2_PIX_FMT_RGB555X:			switch (color) {			case 0:			case 2:				*p = (r_y << 2) | (g_u >> 3);				break;			case 1:			case 3:				*p = (g_u << 5) | b_v;				break;			}			break;		}	}}static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,		int hmax, int line, int count, char *timestr){	int  w, i, j;	int pos = inipos;	char *s;	u8 chr;	/* We will just duplicate the second pixel at the packet */	wmax /= 2;	/* Generate a standard color bar pattern */	for (w = 0; w < wmax; w++) {		int colorpos = ((w + count) * 8/(wmax + 1)) % 8;		gen_twopix(fh, basep + pos, colorpos);		pos += 4; /* only 16 bpp supported for now */	}	/* Checks if it is possible to show timestamp */	if (TSTAMP_MAX_Y >= hmax)		goto end;	if (TSTAMP_MIN_X + strlen(timestr) >= wmax)		goto end;	/* Print stream time */	if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {		j = TSTAMP_MIN_X;		for (s = timestr; *s; s++) {			chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];			for (i = 0; i < 7; i++) {				pos = inipos + j * 2;				/* Draw white font on black background */				if (chr & 1 << (7 - i))					gen_twopix(fh, basep + pos, WHITE);				else					gen_twopix(fh, basep + pos, BLACK);				j++;			}		}	}end:	return;}static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf){	struct vivi_dev *dev = fh->dev;	int h , pos = 0;	int hmax  = buf->vb.height;	int wmax  = buf->vb.width;	struct timeval ts;	char *tmpbuf;	void *vbuf = videobuf_to_vmalloc(&buf->vb);	if (!vbuf)		return;	tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);	if (!tmpbuf)		return;	for (h = 0; h < hmax; h++) {		gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,			 dev->timestr);		memcpy(vbuf + pos, tmpbuf, wmax * 2);		pos += wmax*2;	}	dev->mv_count++;	kfree(tmpbuf);

⌨️ 快捷键说明

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