Commit 9701dc94 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB (12770): Add tm6000 driver to staging tree

Adds a driver for Trident TV Master tm5600/tm6000 chips.

Those USB devices are usually found with a Xceive xc2028/xc3028
tuner, although the firmware seems to be modified to work with
those chips on some older devices.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent e40152ee
config VIDEO_TM6000
tristate "TV Master TM5600/6000 driver"
select VIDEO_V4L2
select TUNER_XC2028
select VIDEO_USB_ISOC
select VIDEOBUF_VMALLOC
help
Support for TM5600/TM6000 USB Device
Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the usb bus, so you need
an external software decoder to watch TV on your computer.
Say Y if you own such a device and want to use it.
tm6000-objs := tm6000-cards.o \
tm6000-core.o \
tm6000-i2c.o \
tm6000-video.o
obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
EXTRA_CFLAGS = -Idrivers/media/video
/*
tm6000-cards.c - driver for TM5600/TM6000 USB video capture devices
Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
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/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/usb.h>
#include <linux/version.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
#include "tm6000.h"
#define TM6000_BOARD_UNKNOWN 0
#define TM5600_BOARD_GENERIC 1
#define TM6000_BOARD_GENERIC 2
#define TM5600_BOARD_10MOONS_UT821 3
#define TM6000_BOARD_10MOONS_UT330 4
#define TM6000_BOARD_ADSTECH_DUAL_TV 5
#define TM6000_MAXBOARDS 16
static unsigned int card[] = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
struct tm6000_board {
char *name;
struct tm6000_capabilities caps;
int tuner_type; /* type of the tuner */
int tuner_addr; /* tuner address */
};
struct tm6000_board tm6000_boards[] = {
[TM6000_BOARD_UNKNOWN] = {
.name = "Unknown tm6000 video grabber",
.caps = {
.has_tuner = 1,
},
},
[TM5600_BOARD_GENERIC] = {
.name = "Generic tm5600 board",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0xc2,
.caps = {
.has_tuner = 1,
},
},
[TM6000_BOARD_GENERIC] = {
.name = "Generic tm6000 board",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0xc2,
.caps = {
.has_tuner = 1,
.has_dvb = 1,
},
},
[TM5600_BOARD_10MOONS_UT821] = {
.name = "10Moons UT 821",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0xc2,
.caps = {
.has_tuner = 1,
.has_eeprom = 1,
},
},
[TM6000_BOARD_10MOONS_UT330] = {
.name = "10Moons UT 330",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0xc8,
.caps = {
.has_tuner = 1,
.has_dvb = 1,
.has_zl10353 = 1,
.has_eeprom = 1,
},
},
[TM6000_BOARD_ADSTECH_DUAL_TV] = {
.name = "ADSTECH Dual TV USB",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0xc8,
.caps = {
.has_tuner = 1,
.has_tda9874 = 1,
.has_dvb = 1,
.has_zl10353 = 1,
.has_eeprom = 1,
},
},
};
/* table of devices that work with this driver */
struct usb_device_id tm6000_id_table [] = {
{ USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_10MOONS_UT821 },
{ USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV },
{ },
};
static int tm6000_init_dev(struct tm6000_core *dev)
{
struct v4l2_frequency f;
int rc = 0;
mutex_init(&dev->lock);
mutex_lock(&dev->lock);
/* Initializa board-specific data */
dev->tuner_type = tm6000_boards[dev->model].tuner_type;
dev->tuner_addr = tm6000_boards[dev->model].tuner_addr;
dev->caps = tm6000_boards[dev->model].caps;
/* initialize hardware */
rc=tm6000_init (dev);
if (rc<0)
goto err;
/* register i2c bus */
rc=tm6000_i2c_register(dev);
if (rc<0)
goto err;
/* register and initialize V4L2 */
rc=tm6000_v4l2_register(dev);
if (rc<0)
goto err;
/* Request tuner */
request_module ("tuner");
// norm=V4L2_STD_NTSC_M;
dev->norm=V4L2_STD_PAL_M;
tm6000_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm);
/* configure tuner */
f.tuner = 0;
f.type = V4L2_TUNER_ANALOG_TV;
f.frequency = 3092; /* 193.25 MHz */
dev->freq = f.frequency;
tm6000_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
err:
mutex_unlock(&dev->lock);
return rc;
}
/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
static void get_max_endpoint ( struct usb_device *usbdev,
char *msgtype,
struct usb_host_endpoint *curr_e,
unsigned int *maxsize,
struct usb_host_endpoint **ep )
{
u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize);
unsigned int size = tmp & 0x7ff;
if (usbdev->speed == USB_SPEED_HIGH)
size = size * hb_mult (tmp);
if (size>*maxsize) {
*ep = curr_e;
*maxsize = size;
printk("tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n",
msgtype, curr_e->desc.bEndpointAddress,
size);
}
}
/*
* tm6000_usb_probe()
* checks for supported devices
*/
static int tm6000_usb_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_device *usbdev;
struct tm6000_core *dev = NULL;
int i,rc=0;
int nr=0;
char *speed;
usbdev=usb_get_dev(interface_to_usbdev(interface));
/* Selects the proper interface */
rc=usb_set_interface(usbdev,0,1);
if (rc<0)
goto err;
/* Check to see next free device and mark as used */
nr=find_first_zero_bit(&tm6000_devused,TM6000_MAXBOARDS);
if (nr >= TM6000_MAXBOARDS) {
printk ("tm6000: Supports only %i em28xx boards.\n",TM6000_MAXBOARDS);
usb_put_dev(usbdev);
return -ENOMEM;
}
/* Create and initialize dev struct */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
printk ("tm6000" ": out of memory!\n");
usb_put_dev(usbdev);
return -ENOMEM;
}
spin_lock_init(&dev->slock);
/* Increment usage count */
tm6000_devused|=1<<nr;
dev->udev= usbdev;
dev->model=id->driver_info;
snprintf(dev->name, 29, "tm6000 #%d", nr);
dev->devno=nr;
switch (usbdev->speed) {
case USB_SPEED_LOW:
speed = "1.5";
break;
case USB_SPEED_UNKNOWN:
case USB_SPEED_FULL:
speed = "12";
break;
case USB_SPEED_HIGH:
speed = "480";
break;
default:
speed = "unknown";
}
/* Get endpoints */
for (i = 0; i < interface->num_altsetting; i++) {
int ep;
for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
struct usb_host_endpoint *e;
int dir_out;
e = &interface->altsetting[i].endpoint[ep];
dir_out = ((e->desc.bEndpointAddress &
USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
printk("tm6000: alt %d, interface %i, class %i\n",
i,
interface->altsetting[i].desc.bInterfaceNumber,
interface->altsetting[i].desc.bInterfaceClass);
switch (e->desc.bmAttributes) {
case USB_ENDPOINT_XFER_BULK:
if (!dir_out) {
get_max_endpoint (usbdev, "Bulk IN", e,
&dev->max_bulk_in,
&dev->bulk_in);
} else {
get_max_endpoint (usbdev, "Bulk OUT", e,
&dev->max_bulk_out,
&dev->bulk_out);
}
break;
case USB_ENDPOINT_XFER_ISOC:
if (!dir_out) {
get_max_endpoint (usbdev, "ISOC IN", e,
&dev->max_isoc_in,
&dev->isoc_in);
} else {
get_max_endpoint (usbdev, "ISOC OUT", e,
&dev->max_isoc_out,
&dev->isoc_out);
}
break;
}
}
}
if (interface->altsetting->desc.bAlternateSetting) {
printk("selecting alt setting %d\n",
interface->altsetting->desc.bAlternateSetting);
rc = usb_set_interface (usbdev,
interface->altsetting->desc.bInterfaceNumber,
interface->altsetting->desc.bAlternateSetting);
if (rc<0)
goto err;
}
printk("tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n",
speed,
le16_to_cpu(dev->udev->descriptor.idVendor),
le16_to_cpu(dev->udev->descriptor.idProduct),
interface->altsetting->desc.bInterfaceNumber);
/* check if the the device has the iso in endpoint at the correct place */
if (!dev->isoc_in) {
printk("tm6000: probing error: no IN ISOC endpoint!\n");
rc= -ENODEV;
goto err;
}
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
printk("tm6000: Found %s\n", tm6000_boards[dev->model].name);
rc=tm6000_init_dev(dev);
if (rc<0)
goto err;
return 0;
err:
tm6000_devused&=~(1<<nr);
usb_put_dev(usbdev);
kfree(dev);
return rc;
}
/*
* tm6000_usb_disconnect()
* called when the device gets diconencted
* video device will be unregistered on v4l2_close in case it is still open
*/
static void tm6000_usb_disconnect(struct usb_interface *interface)
{
struct tm6000_core *dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!dev)
return;
tm6000_i2c_unregister(dev);
printk("tm6000: disconnecting %s\n", dev->name);
mutex_lock(&dev->lock);
tm6000_i2c_unregister(dev);
tm6000_v4l2_unregister(dev);
// wake_up_interruptible_all(&dev->open);
dev->state |= DEV_DISCONNECTED;
mutex_unlock(&dev->lock);
}
static struct usb_driver tm6000_usb_driver = {
.name = "tm6000",
.probe = tm6000_usb_probe,
.disconnect = tm6000_usb_disconnect,
.id_table = tm6000_id_table,
};
static int __init tm6000_module_init(void)
{
int result;
printk(KERN_INFO "tm6000" " v4l2 driver version %d.%d.%d loaded\n",
(TM6000_VERSION >> 16) & 0xff,
(TM6000_VERSION >> 8) & 0xff, TM6000_VERSION & 0xff);
/* register this driver with the USB subsystem */
result = usb_register(&tm6000_usb_driver);
if (result)
printk("tm6000"
" usb_register failed. Error number %d.\n", result);
return result;
}
static void __exit tm6000_module_exit(void)
{
/* deregister at USB subsystem */
usb_deregister(&tm6000_usb_driver);
}
module_init(tm6000_module_init);
module_exit(tm6000_module_exit);
MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000 USB2 adapter");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_LICENSE("GPL");
This diff is collapsed.
This diff is collapsed.
/*
tm6000-regs.h - driver for TM5600/TM6000 USB video capture devices
Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
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.
*/
/*
* Define TV Master TM5600/TM6000 Request codes
*/
#define REQ_00_SET_IR_VALUE 0
#define REQ_01_SET_WAKEUP_IRCODE 1
#define REQ_02_GET_IR_CODE 2
#define REQ_03_SET_GET_MCU_PIN 3
#define REQ_04_EN_DISABLE_MCU_INT 4
#define REQ_05_SET_GET_USBREG 5
/* Write: RegNum, Value, 0 */
/* Read : RegNum, Value, 1, RegStatus */
#define REQ_06_SET_GET_USBREG_BIT 6
#define REQ_07_SET_GET_AVREG 7
/* Write: RegNum, Value, 0 */
/* Read : RegNum, Value, 1, RegStatus */
#define REQ_08_SET_GET_AVREG_BIT 8
#define REQ_09_SET_GET_TUNER_FQ 9
#define REQ_10_SET_TUNER_SYSTEM 10
#define REQ_11_SET_EEPROM_ADDR 11
#define REQ_12_SET_GET_EEPROMBYTE 12
#define REQ_13_GET_EEPROM_SEQREAD 13
#define REQ_14_SET_GET_EEPROM_PAGE 14
#define REQ_15_SET_GET_I2CBYTE 15
/* Write: Subaddr, Slave Addr, value, 0 */
/* Read : Subaddr, Slave Addr, value, 1 */
#define REQ_16_SET_GET_I2CSEQ 16
/* Subaddr, Slave Addr, 0, length */
#define REQ_17_SET_GET_I2CFP 17
/* Write: Slave Addr, register, value */
/* Read : Slave Addr, register, 2, data */
/*
* Define TV Master TM5600/TM6000 GPIO lines
*/
#define TM6000_GPIO_CLK 0x101
#define TM6000_GPIO_DATA 0x100
#define TM6000_GPIO_1 0x102
#define TM6000_GPIO_2 0x103
#define TM6000_GPIO_3 0x104
#define TM6000_GPIO_4 0x300
#define TM6000_GPIO_5 0x301
#define TM6000_GPIO_6 0x304
#define TM6000_GPIO_7 0x305
/*
* Define TV Master TM5600/TM6000 URB message codes and length
*/
#define TM6000_URB_MSG_LEN 180
enum {
TM6000_URB_MSG_VIDEO=1,
TM6000_URB_MSG_AUDIO,
TM6000_URB_MSG_VBI,
TM6000_URB_MSG_PTS,
TM6000_URB_MSG_ERR,
};
/*
tm6000-buf.c - driver for TM5600/TM6000 USB video capture devices
Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
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/videodev2.h>
struct usb_isoc_ctl {
/* max packet size of isoc transaction */
int max_pkt_size;
/* number of allocated urbs */
int num_bufs;
/* urb for isoc transfers */
struct urb **urb;
/* transfer buffers for isoc transfer */
char **transfer_buffer;
/* Last buffer command and region */
u8 cmd;
int pos, size, pktsize;
/* Last field: ODD or EVEN? */
int field;
};
This diff is collapsed.
/*
tm6000.h - driver for TM5600/TM6000 USB video capture devices
Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
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.
*/
// Use the tm6000-hack, instead of the proper initialization code
//#define HACK 1
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/videobuf-vmalloc.h>
#include "tm6000-usb-isoc.h"
#include <linux/i2c.h>
#include <linux/mutex.h>
#define TM6000_VERSION KERNEL_VERSION(0, 0, 1)
/* Inputs */
#define TM6000_INPUT_TV 0
#define TM6000_INPUT_COMPOSITE 1
#define TM6000_INPUT_SVIDEO 2
/* ------------------------------------------------------------------
Basic structures
------------------------------------------------------------------*/
struct tm6000_fmt {
char *name;
u32 fourcc; /* v4l2 format id */
int depth;
};
/* buffer for one video frame */
struct tm6000_buffer {
/* common v4l buffer stuff -- must be first */
struct videobuf_buffer vb;
struct tm6000_fmt *fmt;
};
struct tm6000_dmaqueue {
struct list_head active;
struct list_head queued;
struct timer_list timeout;
/* thread for generating video stream*/
struct task_struct *kthread;
wait_queue_head_t wq;
/* Counters to control fps rate */
int frame;
int ini_jiffies;
};
/* device states */
enum tm6000_core_state {
DEV_INITIALIZED = 0x01,
DEV_DISCONNECTED = 0x02,
DEV_MISCONFIGURED = 0x04,
};
/* io methods */
enum tm6000_io_method {
IO_NONE,
IO_READ,
IO_MMAP,
};
enum tm6000_mode {
TM6000_MODE_UNKNOWN=0,
TM6000_MODE_ANALOG,
TM6000_MODE_DIGITAL,
};
struct tm6000_capabilities {
unsigned int has_tuner:1;
unsigned int has_tda9874:1;
unsigned int has_dvb:1;
unsigned int has_zl10353:1;
unsigned int has_eeprom:1;
};
struct tm6000_core {
/* generic device properties */
char name[30]; /* name (including minor) of the device */
int model; /* index in the device_data struct */
int devno; /* marks the number of this device */
v4l2_std_id norm; /* Current norm */
enum tm6000_core_state state;
/* Device Capabilities*/
struct tm6000_capabilities caps;
/* Tuner configuration */
int tuner_type; /* type of the tuner */
int tuner_addr; /* tuner address */
/* i2c i/o */
struct i2c_adapter i2c_adap;
struct i2c_client i2c_client;
/* video for linux */
struct list_head tm6000_corelist;
int users;
/* various device info */
unsigned int resources;
struct video_device vfd;
struct tm6000_dmaqueue vidq;
int input;
int freq;
unsigned int fourcc;
enum tm6000_mode mode;
/* locks */
struct mutex lock;
/* usb transfer */
struct usb_device *udev; /* the usb device */
struct usb_host_endpoint *bulk_in, *bulk_out, *isoc_in, *isoc_out;
unsigned int max_bulk_in, max_bulk_out;
unsigned int max_isoc_in, max_isoc_out;
/* scaler!=0 if scaler is active*/
int scaler;
/* Isoc control struct */
struct usb_isoc_ctl isoc_ctl;
spinlock_t slock;
};
struct tm6000_fh {
struct tm6000_core *dev;
/* video capture */
struct tm6000_fmt *fmt;
unsigned int width,height;
struct videobuf_queue vb_vidq;
enum v4l2_buf_type type;
};
#define TM6000_STD V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc| \
V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \
V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM
/* In tm6000-core.c */
extern unsigned long tm6000_devused;
int tm6000_read_write_usb (struct tm6000_core *dev, u8 reqtype, u8 req,
u16 value, u16 index, u8 *buf, u16 len);
int tm6000_get_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index);
int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index);
int tm6000_init (struct tm6000_core *dev);
int tm6000_init_after_firmware (struct tm6000_core *dev);
int tm6000_init_analog_mode (struct tm6000_core *dev);
int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm);
int tm6000_set_audio_bitrate (struct tm6000_core *dev, int bitrate);
int tm6000_v4l2_register(struct tm6000_core *dev);
int tm6000_v4l2_unregister(struct tm6000_core *dev);
int tm6000_v4l2_exit(void);
void tm6000_set_fourcc_format(struct tm6000_core *dev);
/* In tm6000-i2c.c */
int tm6000_i2c_register(struct tm6000_core *dev);
int tm6000_i2c_unregister(struct tm6000_core *dev);
void tm6000_i2c_call_clients(struct tm6000_core *dev, unsigned int cmd,
void *arg);
/* In tm6000-queue.c */
int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma);
int tm6000_vidioc_streamon(struct file *file, void *priv,
enum v4l2_buf_type i);
int tm6000_vidioc_streamoff(struct file *file, void *priv,
enum v4l2_buf_type i);
int tm6000_vidioc_reqbufs (struct file *file, void *priv,
struct v4l2_requestbuffers *rb);
int tm6000_vidioc_querybuf (struct file *file, void *priv,
struct v4l2_buffer *b);
int tm6000_vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *b);
int tm6000_vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *b);
ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count,
loff_t * f_pos);
unsigned int tm6000_v4l2_poll(struct file *file,
struct poll_table_struct *wait);
int tm6000_queue_init(struct tm6000_core *dev);
/* Debug stuff */
extern int tm6000_debug;
#define dprintk(dev, level, fmt, arg...) do {\
if (tm6000_debug & level) \
printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \
dev->name, __FUNCTION__ , ##arg); } while (0)
#define V4L2_DEBUG_REG 0x0004
#define V4L2_DEBUG_I2C 0x0008
#define V4L2_DEBUG_QUEUE 0x0010
#define V4L2_DEBUG_ISOC 0x0020
#define V4L2_DEBUG_RES_LOCK 0x0040 /* Resource locking */
#define V4L2_DEBUG_OPEN 0x0080 /* video open/close debug */
#define tm6000_err(fmt, arg...) do {\
printk(KERN_ERR "tm6000 %s :"fmt, \
__FUNCTION__ , ##arg); } while (0)
......@@ -369,6 +369,7 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
#define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
#define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
#define V4L2_PIX_FMT_TM6000 v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
/*
* F O R M A T E N U M E R A T I O N
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment