/drivers/staging/tm6000/tm6000-video.c
C | 1812 lines | 1370 code | 306 blank | 136 comment | 204 complexity | 2eae5d81cc277187f5c3267cd9aafc78 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- * - Fixed module load/unload
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #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/random.h>
- #include <linux/version.h>
- #include <linux/usb.h>
- #include <linux/videodev2.h>
- #include <media/v4l2-ioctl.h>
- #include <media/tuner.h>
- #include <linux/interrupt.h>
- #include <linux/kthread.h>
- #include <linux/highmem.h>
- #include <linux/freezer.h>
- #include "tm6000-regs.h"
- #include "tm6000.h"
- #define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
- /* Limits minimum and default number of buffers */
- #define TM6000_MIN_BUF 4
- #define TM6000_DEF_BUF 8
- #define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */
- /* 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 radio_nr = -1; /* /dev/radioN, -1 for autodetect */
- /* Debug level */
- int tm6000_debug;
- EXPORT_SYMBOL_GPL(tm6000_debug);
- static const struct v4l2_queryctrl no_ctrl = {
- .name = "42",
- .flags = V4L2_CTRL_FLAG_DISABLED,
- };
- /* supported controls */
- static struct v4l2_queryctrl tm6000_qctrl[] = {
- {
- .id = V4L2_CID_BRIGHTNESS,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Brightness",
- .minimum = 0,
- .maximum = 255,
- .step = 1,
- .default_value = 54,
- .flags = 0,
- }, {
- .id = V4L2_CID_CONTRAST,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Contrast",
- .minimum = 0,
- .maximum = 255,
- .step = 0x1,
- .default_value = 119,
- .flags = 0,
- }, {
- .id = V4L2_CID_SATURATION,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Saturation",
- .minimum = 0,
- .maximum = 255,
- .step = 0x1,
- .default_value = 112,
- .flags = 0,
- }, {
- .id = V4L2_CID_HUE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Hue",
- .minimum = -128,
- .maximum = 127,
- .step = 0x1,
- .default_value = 0,
- .flags = 0,
- },
- /* --- 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 = -15,
- .maximum = 15,
- .step = 1,
- .default_value = 0,
- .type = V4L2_CTRL_TYPE_INTEGER,
- }
- };
- static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl);
- static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)];
- static struct tm6000_fmt format[] = {
- {
- .name = "4:2:2, packed, YVY2",
- .fourcc = V4L2_PIX_FMT_YUYV,
- .depth = 16,
- }, {
- .name = "4:2:2, packed, UYVY",
- .fourcc = V4L2_PIX_FMT_UYVY,
- .depth = 16,
- }, {
- .name = "A/V + VBI mux packet",
- .fourcc = V4L2_PIX_FMT_TM6000,
- .depth = 16,
- }
- };
- static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
- {
- unsigned int i;
- for (i = 0; i < CTRLS; i++)
- if (tm6000_qctrl[i].id == id)
- return tm6000_qctrl+i;
- return NULL;
- }
- /* ------------------------------------------------------------------
- * DMA and thread functions
- * ------------------------------------------------------------------
- */
- #define norm_maxw(a) 720
- #define norm_maxh(a) 576
- #define norm_minw(a) norm_maxw(a)
- #define norm_minh(a) norm_maxh(a)
- /*
- * video-buf generic routine to get the next available buffer
- */
- static inline void get_next_buf(struct tm6000_dmaqueue *dma_q,
- struct tm6000_buffer **buf)
- {
- struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
- char *outp;
- if (list_empty(&dma_q->active)) {
- dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n");
- *buf = NULL;
- return;
- }
- *buf = list_entry(dma_q->active.next,
- struct tm6000_buffer, vb.queue);
- if (!buf)
- return;
- /* Cleans up buffer - Useful for testing for frame/URB loss */
- outp = videobuf_to_vmalloc(&(*buf)->vb);
- return;
- }
- /*
- * Announces that a buffer were filled and request the next
- */
- static inline void buffer_filled(struct tm6000_core *dev,
- struct tm6000_dmaqueue *dma_q,
- struct tm6000_buffer *buf)
- {
- /* Advice that buffer was filled */
- dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i);
- buf->vb.state = VIDEOBUF_DONE;
- buf->vb.field_count++;
- do_gettimeofday(&buf->vb.ts);
- list_del(&buf->vb.queue);
- wake_up(&buf->vb.done);
- }
- const char *tm6000_msg_type[] = {
- "unknown(0)", /* 0 */
- "video", /* 1 */
- "audio", /* 2 */
- "vbi", /* 3 */
- "pts", /* 4 */
- "err", /* 5 */
- "unknown(6)", /* 6 */
- "unknown(7)", /* 7 */
- };
- /*
- * Identify the tm5600/6000 buffer header type and properly handles
- */
- static int copy_streams(u8 *data, unsigned long len,
- struct urb *urb)
- {
- struct tm6000_dmaqueue *dma_q = urb->context;
- struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
- u8 *ptr = data, *endp = data+len, c;
- unsigned long header = 0;
- int rc = 0;
- unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0;
- struct tm6000_buffer *vbuf = NULL;
- char *voutp = NULL;
- unsigned int linewidth;
- if (!dev->radio) {
- /* get video buffer */
- get_next_buf(dma_q, &vbuf);
- if (!vbuf)
- return rc;
- voutp = videobuf_to_vmalloc(&vbuf->vb);
- if (!voutp)
- return 0;
- }
-