mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 05:04:09 +08:00
Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (44 commits) V4L/DVB (5571): V4l1-compat: Make VIDIOCSPICT return errors in a useful way V4L/DVB (5624): Radio-maestro.c cleanup V4L/DVB (5623): Dsbr100.c Replace usb_dsbr100_do_ioctl to use video_ioctl2 V4L/DVB (5622): Radio-zoltrix.c cleanup V4L/DVB (5621): Radio-cadet.c Replace cadet_do_ioctl to use video_ioctl2 V4L/DVB (5619): Dvb-usb: fix typo V4L/DVB (5618): Cx88: Drop the generic i2c client from cx88-vp3054-i2c V4L/DVB (5617): V4L2: videodev, allow debugging V4L/DVB (5614): M920x: Disable second adapter on LifeView TV Walker Twin V4L/DVB (5613): M920x: loosen up 80-col limit V4L/DVB (5612): M920x: rename function prefixes from m9206_foo to m920x_foo V4L/DVB (5611): M920x: replace deb_rc with deb V4L/DVB (5610): M920x: remove duplicated code V4L/DVB (5609): M920x: group like functions together V4L/DVB (5608): M920x: various whitespace cleanups V4L/DVB (5607): M920x: Initial support for devices likely manufactured by Dposh V4L/DVB (5606): M920x: add "c-basic-offset: 8" to help emacs to enforce tabbing V4L/DVB (5605): M920x: Add support for LifeView TV Walker Twin V4L/DVB (5603): V4L: Prevent queueing queued buffers. V4L/DVB (5602): Enable DiSEqC in Starbox II (vp7021a) ...
This commit is contained in:
commit
57a44415be
@ -52,7 +52,7 @@
|
||||
51 -> ProVideo PV952 [1540:9524]
|
||||
52 -> AverMedia AverTV/305 [1461:2108]
|
||||
53 -> ASUS TV-FM 7135 [1043:4845]
|
||||
54 -> LifeView FlyTV Platinum FM / Gold [5168:0214,1489:0214,5168:0304]
|
||||
54 -> LifeView FlyTV Platinum FM / Gold [5168:0214,5168:5214,1489:0214,5168:0304]
|
||||
55 -> LifeView FlyDVB-T DUO / MSI TV@nywhere Duo [5168:0306,4E42:0306]
|
||||
56 -> Avermedia AVerTV 307 [1461:a70a]
|
||||
57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
|
||||
@ -111,3 +111,6 @@
|
||||
110 -> Avermedia M102 [1461:f31e]
|
||||
111 -> ASUS P7131 4871 [1043:4871]
|
||||
112 -> ASUSTeK P7131 Hybrid [1043:4876]
|
||||
113 -> Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM) [1019:4cb6]
|
||||
114 -> KWorld DVB-T 210 [17de:7250]
|
||||
115 -> Sabrent PCMCIA TV-PCB05 [0919:2003]
|
||||
|
@ -355,6 +355,9 @@ devices assembling the SN9C1xx PC camera controllers:
|
||||
|
||||
Vendor ID Product ID
|
||||
--------- ----------
|
||||
0x0458 0x7025
|
||||
0x045e 0x00f5
|
||||
0x045e 0x00f7
|
||||
0x0471 0x0327
|
||||
0x0471 0x0328
|
||||
0x0c45 0x6001
|
||||
@ -432,7 +435,7 @@ Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120
|
||||
HV7131D Hynix Semiconductor | Yes No No No
|
||||
HV7131R Hynix Semiconductor | No Yes Yes Yes
|
||||
MI-0343 Micron Technology | Yes No No No
|
||||
MI-0360 Micron Technology | No Yes No No
|
||||
MI-0360 Micron Technology | No Yes Yes Yes
|
||||
OV7630 OmniVision Technologies | Yes Yes No No
|
||||
OV7660 OmniVision Technologies | No No Yes Yes
|
||||
PAS106B PixArt Imaging | Yes No No No
|
||||
@ -478,13 +481,12 @@ scaling factor is restored to 1.
|
||||
This driver supports two different video formats: the first one is the "8-bit
|
||||
Sequential Bayer" format and can be used to obtain uncompressed video data
|
||||
from the device through the current I/O method, while the second one provides
|
||||
"raw" compressed video data (without frame headers not related to the
|
||||
compressed data). The compression quality may vary from 0 to 1 and can be
|
||||
selected or queried thanks to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2
|
||||
ioctl's. For maximum flexibility, both the default active video format and the
|
||||
default compression quality depend on how the image sensor being used is
|
||||
initialized (as described in the documentation of the API for the image sensors
|
||||
supplied by this driver).
|
||||
either "raw" compressed video data (without frame headers not related to the
|
||||
compressed data) or standard JPEG (with frame headers). The compression quality
|
||||
may vary from 0 to 1 and can be selected or queried thanks to the
|
||||
VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum flexibility,
|
||||
both the default active video format and the default compression quality
|
||||
depend on how the image sensor being used is initialized.
|
||||
|
||||
|
||||
11. Video frame formats [1]
|
||||
|
@ -87,6 +87,14 @@ config VIDEO_TVEEPROM
|
||||
tristate
|
||||
depends on I2C
|
||||
|
||||
config DAB
|
||||
boolean "DAB adapters"
|
||||
default y
|
||||
---help---
|
||||
Allow selecting support for for Digital Audio Broadcasting (DAB)
|
||||
Receiver adapters.
|
||||
|
||||
if DAB
|
||||
config USB_DABUSB
|
||||
tristate "DABUSB driver"
|
||||
depends on USB
|
||||
@ -100,5 +108,6 @@ config USB_DABUSB
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called dabusb.
|
||||
endif # DAB
|
||||
|
||||
endmenu
|
||||
|
@ -5,4 +5,4 @@
|
||||
obj-y := common/
|
||||
obj-$(CONFIG_VIDEO_DEV) += video/
|
||||
obj-$(CONFIG_VIDEO_DEV) += radio/
|
||||
obj-$(CONFIG_DVB) += dvb/
|
||||
obj-$(CONFIG_DVB_CORE) += dvb/
|
||||
|
@ -136,28 +136,45 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa
|
||||
char *mem = vmalloc_32(length);
|
||||
int slen = 0;
|
||||
|
||||
if (NULL == mem) {
|
||||
return NULL;
|
||||
}
|
||||
if (NULL == mem)
|
||||
goto err_null;
|
||||
|
||||
if (!(pt->slist = vmalloc_to_sg(mem, pages))) {
|
||||
vfree(mem);
|
||||
return NULL;
|
||||
}
|
||||
if (!(pt->slist = vmalloc_to_sg(mem, pages)))
|
||||
goto err_free_mem;
|
||||
|
||||
if (saa7146_pgtable_alloc(pci, pt)) {
|
||||
kfree(pt->slist);
|
||||
pt->slist = NULL;
|
||||
vfree(mem);
|
||||
return NULL;
|
||||
}
|
||||
if (saa7146_pgtable_alloc(pci, pt))
|
||||
goto err_free_slist;
|
||||
|
||||
slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE);
|
||||
if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) {
|
||||
return NULL;
|
||||
}
|
||||
pt->nents = pages;
|
||||
slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE);
|
||||
if (0 == slen)
|
||||
goto err_free_pgtable;
|
||||
|
||||
if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen))
|
||||
goto err_unmap_sg;
|
||||
|
||||
return mem;
|
||||
|
||||
err_unmap_sg:
|
||||
pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
|
||||
err_free_pgtable:
|
||||
saa7146_pgtable_free(pci, pt);
|
||||
err_free_slist:
|
||||
kfree(pt->slist);
|
||||
pt->slist = NULL;
|
||||
err_free_mem:
|
||||
vfree(mem);
|
||||
err_null:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt)
|
||||
{
|
||||
pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
|
||||
saa7146_pgtable_free(pci, pt);
|
||||
kfree(pt->slist);
|
||||
pt->slist = NULL;
|
||||
vfree(mem);
|
||||
}
|
||||
|
||||
void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
|
||||
@ -166,8 +183,6 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
|
||||
return;
|
||||
pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
|
||||
pt->cpu = NULL;
|
||||
kfree(pt->slist);
|
||||
pt->slist = NULL;
|
||||
}
|
||||
|
||||
int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
|
||||
@ -528,6 +543,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
|
||||
EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
|
||||
EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
|
||||
EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
|
||||
EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable);
|
||||
EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
|
||||
|
||||
EXPORT_SYMBOL_GPL(saa7146_setgpio);
|
||||
|
@ -307,7 +307,6 @@ static int fops_release(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg);
|
||||
static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
/*
|
||||
|
@ -2,25 +2,17 @@
|
||||
# Multimedia device configuration
|
||||
#
|
||||
|
||||
menu "Digital Video Broadcasting Devices"
|
||||
|
||||
config DVB
|
||||
bool "DVB For Linux"
|
||||
depends on NET && INET
|
||||
---help---
|
||||
Support Digital Video Broadcasting hardware. Enable this if you
|
||||
own a DVB adapter and want to use it or if you compile Linux for
|
||||
a digital SetTopBox.
|
||||
|
||||
API specs and user tools are available from <http://www.linuxtv.org/>.
|
||||
|
||||
Please report problems regarding this driver to the LinuxDVB
|
||||
mailing list.
|
||||
|
||||
If unsure say N.
|
||||
|
||||
source "drivers/media/dvb/dvb-core/Kconfig"
|
||||
|
||||
menuconfig DVB_CAPTURE_DRIVERS
|
||||
bool "DVB/ATSC adapters"
|
||||
depends on DVB_CORE
|
||||
default y
|
||||
---help---
|
||||
Say Y to select Digital TV adapters
|
||||
|
||||
if DVB_CAPTURE_DRIVERS
|
||||
|
||||
comment "Supported SAA7146 based PCI Adapters"
|
||||
depends on DVB_CORE && PCI && I2C
|
||||
source "drivers/media/dvb/ttpci/Kconfig"
|
||||
@ -48,4 +40,4 @@ comment "Supported DVB Frontends"
|
||||
depends on DVB_CORE
|
||||
source "drivers/media/dvb/frontends/Kconfig"
|
||||
|
||||
endmenu
|
||||
endif # DVB_CAPTURE_DRIVERS
|
||||
|
@ -1,12 +1,22 @@
|
||||
config DVB_CORE
|
||||
tristate "DVB Core Support"
|
||||
depends on DVB
|
||||
tristate "DVB for Linux"
|
||||
depends on NET && INET
|
||||
select CRC32
|
||||
help
|
||||
Support Digital Video Broadcasting hardware. Enable this if you
|
||||
own a DVB adapter and want to use it or if you compile Linux for
|
||||
a digital SetTopBox.
|
||||
|
||||
DVB core utility functions for device handling, software fallbacks etc.
|
||||
Say Y when you have a DVB card and want to use it. Say Y if your want
|
||||
to build your drivers outside the kernel, but need the DVB core. All
|
||||
in-kernel drivers will select this automatically if needed.
|
||||
|
||||
API specs and user tools are available from <http://www.linuxtv.org/>.
|
||||
|
||||
Please report problems regarding this driver to the LinuxDVB
|
||||
mailing list.
|
||||
|
||||
If unsure say N.
|
||||
|
||||
config DVB_CORE_ATTACH
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define USB_VID_COMPRO_UNK 0x145f
|
||||
#define USB_VID_CYPRESS 0x04b4
|
||||
#define USB_VID_DIBCOM 0x10b8
|
||||
#define USB_VID_DPOSH 0x1498
|
||||
#define USB_VID_DVICO 0x0fe9
|
||||
#define USB_VID_EMPIA 0xeb1a
|
||||
#define USB_VID_GENPIX 0x09c0
|
||||
@ -61,6 +62,8 @@
|
||||
#define USB_PID_DIBCOM_STK7700P 0x1e14
|
||||
#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
|
||||
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
|
||||
#define USB_PID_DPOSH_M9206_COLD 0x9206
|
||||
#define USB_PID_DPOSH_M9206_WARM 0xa090
|
||||
#define USB_PID_UNIWILL_STK7700P 0x6003
|
||||
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
|
||||
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
|
||||
@ -145,6 +148,8 @@
|
||||
#define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513
|
||||
#define USB_PID_OPERA1_COLD 0x2830
|
||||
#define USB_PID_OPERA1_WARM 0x3829
|
||||
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514
|
||||
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -119,7 +119,7 @@ struct usb_data_stream_properties {
|
||||
* @caps: capabilities of the DVB USB device.
|
||||
* @pid_filter_count: number of PID filter position in the optional hardware
|
||||
* PID-filter.
|
||||
* @streaming_crtl: called to start and stop the MPEG2-TS streaming of the
|
||||
* @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
|
||||
* device (not URB submitting/killing).
|
||||
* @pid_filter_ctrl: called to en/disable the PID filter, if any.
|
||||
* @pid_filter: called to set/unset a PID for filtering.
|
||||
|
@ -3,8 +3,8 @@
|
||||
* Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.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.
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
@ -22,26 +22,7 @@ static int dvb_usb_m920x_debug;
|
||||
module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
static struct dvb_usb_rc_key megasky_rc_keys [] = {
|
||||
{ 0x0, 0x12, KEY_POWER },
|
||||
{ 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
|
||||
{ 0x0, 0x02, KEY_CHANNELUP },
|
||||
{ 0x0, 0x05, KEY_CHANNELDOWN },
|
||||
{ 0x0, 0x03, KEY_VOLUMEUP },
|
||||
{ 0x0, 0x06, KEY_VOLUMEDOWN },
|
||||
{ 0x0, 0x04, KEY_MUTE },
|
||||
{ 0x0, 0x07, KEY_OK }, /* TS */
|
||||
{ 0x0, 0x08, KEY_STOP },
|
||||
{ 0x0, 0x09, KEY_MENU }, /* swap */
|
||||
{ 0x0, 0x0a, KEY_REWIND },
|
||||
{ 0x0, 0x1b, KEY_PAUSE },
|
||||
{ 0x0, 0x1f, KEY_FASTFORWARD },
|
||||
{ 0x0, 0x0c, KEY_RECORD },
|
||||
{ 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
|
||||
{ 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
|
||||
};
|
||||
|
||||
static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\
|
||||
static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
|
||||
u16 index, void *data, int size)
|
||||
{
|
||||
int ret;
|
||||
@ -55,14 +36,14 @@ static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\
|
||||
}
|
||||
|
||||
if (ret != size) {
|
||||
deb_rc("m920x_read = no data\n");
|
||||
deb("m920x_read = no data\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int m9206_write(struct usb_device *udev, u8 request,
|
||||
static inline int m920x_write(struct usb_device *udev, u8 request,
|
||||
u16 value, u16 index)
|
||||
{
|
||||
int ret;
|
||||
@ -74,32 +55,40 @@ static inline int m9206_write(struct usb_device *udev, u8 request,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m9206_init(struct dvb_usb_device *d)
|
||||
static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Remote controller init. */
|
||||
if (d->props.rc_query) {
|
||||
if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0)
|
||||
return ret;
|
||||
deb("Initialising remote control\n");
|
||||
while (rc_seq->address) {
|
||||
if ((ret = m920x_write(d->udev, M9206_CORE,
|
||||
rc_seq->data,
|
||||
rc_seq->address)) != 0) {
|
||||
deb("Initialising remote control failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0)
|
||||
return ret;
|
||||
rc_seq++;
|
||||
}
|
||||
|
||||
deb("Initialising remote control success\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
struct m9206_state *m = d->priv;
|
||||
struct m920x_state *m = d->priv;
|
||||
int i, ret = 0;
|
||||
u8 rc_state[2];
|
||||
|
||||
if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
|
||||
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
|
||||
goto unlock;
|
||||
|
||||
if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
|
||||
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
|
||||
goto unlock;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
@ -111,6 +100,14 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
goto unlock;
|
||||
|
||||
case 0x88: /* framing error or "invalid code" */
|
||||
case 0x99:
|
||||
case 0xc0:
|
||||
case 0xd8:
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
m->rep_count = 0;
|
||||
goto unlock;
|
||||
|
||||
case 0x93:
|
||||
case 0x92:
|
||||
m->rep_count = 0;
|
||||
@ -118,31 +115,32 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
goto unlock;
|
||||
|
||||
case 0x91:
|
||||
/* For comfort. */
|
||||
/* prevent immediate auto-repeat */
|
||||
if (++m->rep_count > 2)
|
||||
*state = REMOTE_KEY_REPEAT;
|
||||
else
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
goto unlock;
|
||||
|
||||
default:
|
||||
deb_rc("Unexpected rc response %x\n", rc_state[0]);
|
||||
deb("Unexpected rc state %02x\n", rc_state[0]);
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc_state[1] != 0)
|
||||
deb_rc("Unknown rc key %x\n", rc_state[1]);
|
||||
deb("Unknown rc key %02x\n", rc_state[1]);
|
||||
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
unlock:
|
||||
unlock:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
int num)
|
||||
static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i, j;
|
||||
@ -155,33 +153,40 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
return -EAGAIN;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN) ||
|
||||
msg[i].len == 0) {
|
||||
/* For a 0 byte message, I think sending the address to index 0x80|0x40
|
||||
* would be the correct thing to do. However, zero byte messages are
|
||||
* only used for probing, and since we don't know how to get the slave's
|
||||
* ack, we can't probe. */
|
||||
if (msg[i].flags & (I2C_M_NO_RD_ACK | I2C_M_IGNORE_NAK | I2C_M_TEN) || msg[i].len == 0) {
|
||||
/* For a 0 byte message, I think sending the address
|
||||
* to index 0x80|0x40 would be the correct thing to
|
||||
* do. However, zero byte messages are only used for
|
||||
* probing, and since we don't know how to get the
|
||||
* slave's ack, we can't probe. */
|
||||
ret = -ENOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
/* Send START & address/RW bit */
|
||||
if (!(msg[i].flags & I2C_M_NOSTART)) {
|
||||
if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), 0x80)) != 0)
|
||||
if ((ret = m920x_write(d->udev, M9206_I2C,
|
||||
(msg[i].addr << 1) |
|
||||
(msg[i].flags & I2C_M_RD ? 0x01 : 0), 0x80)) != 0)
|
||||
goto unlock;
|
||||
/* Should check for ack here, if we knew how. */
|
||||
}
|
||||
if (msg[i].flags & I2C_M_RD) {
|
||||
for (j = 0; j < msg[i].len; j++) {
|
||||
/* Last byte of transaction? Send STOP, otherwise send ACK. */
|
||||
int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01;
|
||||
if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0)
|
||||
/* Last byte of transaction?
|
||||
* Send STOP, otherwise send ACK. */
|
||||
int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x01;
|
||||
|
||||
if ((ret = m920x_read(d->udev, M9206_I2C, 0x0,
|
||||
0x20 | stop,
|
||||
&msg[i].buf[j], 1)) != 0)
|
||||
goto unlock;
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < msg[i].len; j++) {
|
||||
/* Last byte of transaction? Then send STOP. */
|
||||
int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00;
|
||||
if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0)
|
||||
int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x00;
|
||||
|
||||
if ((ret = m920x_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0)
|
||||
goto unlock;
|
||||
/* Should check for ack here too. */
|
||||
}
|
||||
@ -189,25 +194,25 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
}
|
||||
ret = num;
|
||||
|
||||
unlock:
|
||||
unlock:
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 m9206_i2c_func(struct i2c_adapter *adapter)
|
||||
static u32 m920x_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm m9206_i2c_algo = {
|
||||
.master_xfer = m9206_i2c_xfer,
|
||||
.functionality = m9206_i2c_func,
|
||||
static struct i2c_algorithm m920x_i2c_algo = {
|
||||
.master_xfer = m920x_i2c_xfer,
|
||||
.functionality = m920x_i2c_func,
|
||||
};
|
||||
|
||||
|
||||
static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx,
|
||||
int pid)
|
||||
/* pid filter */
|
||||
static int m920x_set_filter(struct dvb_usb_adapter *adap,
|
||||
int type, int idx, int pid)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@ -216,18 +221,18 @@ static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx,
|
||||
|
||||
pid |= 0x8000;
|
||||
|
||||
if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
|
||||
if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
|
||||
if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m9206_update_filters(struct dvb_usb_adapter *adap)
|
||||
static int m920x_update_filters(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct m9206_state *m = adap->dev->priv;
|
||||
struct m920x_state *m = adap->dev->priv;
|
||||
int enabled = m->filtering_enabled;
|
||||
int i, ret = 0, filter = 0;
|
||||
|
||||
@ -236,14 +241,14 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap)
|
||||
enabled = 0;
|
||||
|
||||
/* Disable all filters */
|
||||
if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0)
|
||||
if ((ret = m920x_set_filter(adap, 0x81, 1, enabled)) != 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < M9206_MAX_FILTERS; i++)
|
||||
if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0)
|
||||
if ((ret = m920x_set_filter(adap, 0x81, i + 2, 0)) != 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0)
|
||||
if ((ret = m920x_set_filter(adap, 0x82, 0, 0x0)) != 0)
|
||||
return ret;
|
||||
|
||||
/* Set */
|
||||
@ -252,40 +257,38 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap)
|
||||
if (m->filters[i] == 0)
|
||||
continue;
|
||||
|
||||
if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
|
||||
if ((ret = m920x_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
|
||||
return ret;
|
||||
|
||||
filter++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
|
||||
if ((ret = m920x_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
static int m920x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
struct m9206_state *m = adap->dev->priv;
|
||||
struct m920x_state *m = adap->dev->priv;
|
||||
|
||||
m->filtering_enabled = onoff ? 1 : 0;
|
||||
|
||||
return m9206_update_filters(adap);
|
||||
return m920x_update_filters(adap);
|
||||
}
|
||||
|
||||
static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
|
||||
int onoff)
|
||||
static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
|
||||
{
|
||||
struct m9206_state *m = adap->dev->priv;
|
||||
struct m920x_state *m = adap->dev->priv;
|
||||
|
||||
m->filters[index] = onoff ? pid : 0;
|
||||
|
||||
return m9206_update_filters(adap);
|
||||
return m920x_update_filters(adap);
|
||||
}
|
||||
|
||||
static int m9206_firmware_download(struct usb_device *udev,
|
||||
const struct firmware *fw)
|
||||
static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw)
|
||||
{
|
||||
u16 value, index, size;
|
||||
u8 read[4], *buff;
|
||||
@ -293,13 +296,13 @@ static int m9206_firmware_download(struct usb_device *udev,
|
||||
|
||||
buff = kmalloc(65536, GFP_KERNEL);
|
||||
|
||||
if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
|
||||
if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
|
||||
goto done;
|
||||
deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
|
||||
deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
|
||||
|
||||
if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
|
||||
if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
|
||||
goto done;
|
||||
deb_rc("%x\n", read[0]);
|
||||
deb("%x\n", read[0]);
|
||||
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
|
||||
@ -317,11 +320,11 @@ static int m9206_firmware_download(struct usb_device *udev,
|
||||
memcpy(buff, fw->data + i, size);
|
||||
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
|
||||
M9206_FW,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
value, index, buff, size, 20);
|
||||
M9206_FW,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
value, index, buff, size, 20);
|
||||
if (ret != size) {
|
||||
deb_rc("error while uploading fw!\n");
|
||||
deb("error while uploading fw!\n");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
@ -330,7 +333,7 @@ static int m9206_firmware_download(struct usb_device *udev,
|
||||
i += size;
|
||||
}
|
||||
if (i != fw->size) {
|
||||
deb_rc("bad firmware file!\n");
|
||||
deb("bad firmware file!\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
@ -338,11 +341,11 @@ static int m9206_firmware_download(struct usb_device *udev,
|
||||
|
||||
msleep(36);
|
||||
|
||||
/* m9206 will disconnect itself from the bus after this. */
|
||||
(void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
|
||||
deb_rc("firmware uploaded!\n");
|
||||
/* m920x will disconnect itself from the bus after this. */
|
||||
(void) m920x_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
|
||||
deb("firmware uploaded!\n");
|
||||
|
||||
done:
|
||||
done:
|
||||
kfree(buff);
|
||||
|
||||
return ret;
|
||||
@ -362,7 +365,8 @@ static int m920x_identify_state(struct usb_device *udev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int megasky_mt352_demod_init(struct dvb_frontend *fe)
|
||||
/* demod configurations */
|
||||
static int m920x_mt352_demod_init(struct dvb_frontend *fe)
|
||||
{
|
||||
u8 config[] = { CONFIG, 0x3d };
|
||||
u8 clock[] = { CLOCK_CTL, 0x30 };
|
||||
@ -382,41 +386,18 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe)
|
||||
mt352_write(fe, unk1, ARRAY_SIZE(unk1));
|
||||
mt352_write(fe, unk2, ARRAY_SIZE(unk2));
|
||||
|
||||
deb_rc("Demod init!\n");
|
||||
deb("Demod init!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mt352_config megasky_mt352_config = {
|
||||
static struct mt352_config m920x_mt352_config = {
|
||||
.demod_address = 0x0f,
|
||||
.no_tuner = 1,
|
||||
.demod_init = megasky_mt352_demod_init,
|
||||
.demod_init = m920x_mt352_demod_init,
|
||||
};
|
||||
|
||||
static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb_rc("megasky_frontend_attach!\n");
|
||||
|
||||
if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct qt1010_config megasky_qt1010_config = {
|
||||
.i2c_address = 0x62
|
||||
};
|
||||
|
||||
static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
&megasky_qt1010_config) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tda1004x_config digivox_tda10046_config = {
|
||||
static struct tda1004x_config m920x_tda10046_08_config = {
|
||||
.demod_address = 0x08,
|
||||
.invert = 0,
|
||||
.invert_oclk = 0,
|
||||
@ -428,28 +409,151 @@ static struct tda1004x_config digivox_tda10046_config = {
|
||||
.request_firmware = NULL,
|
||||
};
|
||||
|
||||
static int digivox_tda10046_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb_rc("digivox_tda10046_frontend_attach!\n");
|
||||
static struct tda1004x_config m920x_tda10046_0b_config = {
|
||||
.demod_address = 0x0b,
|
||||
.invert = 0,
|
||||
.invert_oclk = 0,
|
||||
.ts_mode = TDA10046_TS_SERIAL,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.agc_config = TDA10046_AGC_TDA827X,
|
||||
.gpio_config = TDA10046_GPTRI,
|
||||
.request_firmware = NULL, /* uses firmware EEPROM */
|
||||
};
|
||||
|
||||
if ((adap->fe = dvb_attach(tda10046_attach, &digivox_tda10046_config,
|
||||
/* tuner configurations */
|
||||
static struct qt1010_config m920x_qt1010_config = {
|
||||
.i2c_address = 0x62
|
||||
};
|
||||
|
||||
/* Callbacks for DVB USB */
|
||||
static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__FUNCTION__);
|
||||
|
||||
if ((adap->fe = dvb_attach(mt352_attach,
|
||||
&m920x_mt352_config,
|
||||
&adap->dev->i2c_adap)) == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int digivox_tda8275_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
|
||||
NULL) == NULL)
|
||||
return -ENODEV;
|
||||
deb("%s\n",__FUNCTION__);
|
||||
|
||||
if ((adap->fe = dvb_attach(tda10046_attach,
|
||||
&m920x_tda10046_08_config,
|
||||
&adap->dev->i2c_adap)) == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__FUNCTION__);
|
||||
|
||||
if ((adap->fe = dvb_attach(tda10046_attach,
|
||||
&m920x_tda10046_0b_config,
|
||||
&adap->dev->i2c_adap)) == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__FUNCTION__);
|
||||
|
||||
if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__FUNCTION__);
|
||||
|
||||
if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__FUNCTION__);
|
||||
|
||||
if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* device-specific initialization */
|
||||
static struct m920x_inits megasky_rc_init [] = {
|
||||
{ M9206_RC_INIT2, 0xa8 },
|
||||
{ M9206_RC_INIT1, 0x51 },
|
||||
{ } /* terminating entry */
|
||||
};
|
||||
|
||||
static struct m920x_inits tvwalkertwin_rc_init [] = {
|
||||
{ M9206_RC_INIT2, 0x00 },
|
||||
{ M9206_RC_INIT1, 0xef },
|
||||
{ 0xff28, 0x00 },
|
||||
{ 0xff23, 0x00 },
|
||||
{ 0xff21, 0x30 },
|
||||
{ } /* terminating entry */
|
||||
};
|
||||
|
||||
/* ir keymaps */
|
||||
static struct dvb_usb_rc_key megasky_rc_keys [] = {
|
||||
{ 0x0, 0x12, KEY_POWER },
|
||||
{ 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
|
||||
{ 0x0, 0x02, KEY_CHANNELUP },
|
||||
{ 0x0, 0x05, KEY_CHANNELDOWN },
|
||||
{ 0x0, 0x03, KEY_VOLUMEUP },
|
||||
{ 0x0, 0x06, KEY_VOLUMEDOWN },
|
||||
{ 0x0, 0x04, KEY_MUTE },
|
||||
{ 0x0, 0x07, KEY_OK }, /* TS */
|
||||
{ 0x0, 0x08, KEY_STOP },
|
||||
{ 0x0, 0x09, KEY_MENU }, /* swap */
|
||||
{ 0x0, 0x0a, KEY_REWIND },
|
||||
{ 0x0, 0x1b, KEY_PAUSE },
|
||||
{ 0x0, 0x1f, KEY_FASTFORWARD },
|
||||
{ 0x0, 0x0c, KEY_RECORD },
|
||||
{ 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
|
||||
{ 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = {
|
||||
{ 0x0, 0x01, KEY_ZOOM }, /* Full Screen */
|
||||
{ 0x0, 0x02, KEY_CAMERA }, /* snapshot */
|
||||
{ 0x0, 0x03, KEY_MUTE },
|
||||
{ 0x0, 0x04, KEY_REWIND },
|
||||
{ 0x0, 0x05, KEY_PLAYPAUSE }, /* Play/Pause */
|
||||
{ 0x0, 0x06, KEY_FASTFORWARD },
|
||||
{ 0x0, 0x07, KEY_RECORD },
|
||||
{ 0x0, 0x08, KEY_STOP },
|
||||
{ 0x0, 0x09, KEY_TIME }, /* Timeshift */
|
||||
{ 0x0, 0x0c, KEY_COFFEE }, /* Recall */
|
||||
{ 0x0, 0x0e, KEY_CHANNELUP },
|
||||
{ 0x0, 0x12, KEY_POWER },
|
||||
{ 0x0, 0x15, KEY_MENU }, /* source */
|
||||
{ 0x0, 0x18, KEY_CYCLEWINDOWS }, /* TWIN PIP */
|
||||
{ 0x0, 0x1a, KEY_CHANNELDOWN },
|
||||
{ 0x0, 0x1b, KEY_VOLUMEDOWN },
|
||||
{ 0x0, 0x1e, KEY_VOLUMEUP },
|
||||
};
|
||||
|
||||
/* DVB USB Driver stuff */
|
||||
static struct dvb_usb_device_properties megasky_properties;
|
||||
static struct dvb_usb_device_properties digivox_mini_ii_properties;
|
||||
static struct dvb_usb_device_properties tvwalkertwin_properties;
|
||||
static struct dvb_usb_device_properties dposh_properties;
|
||||
|
||||
static int m920x_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
@ -457,19 +561,57 @@ static int m920x_probe(struct usb_interface *intf,
|
||||
struct dvb_usb_device *d;
|
||||
struct usb_host_interface *alt;
|
||||
int ret;
|
||||
struct m920x_inits *rc_init_seq = NULL;
|
||||
int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
|
||||
|
||||
deb_rc("Probed!\n");
|
||||
deb("Probing for m920x device at interface %d\n", bInterfaceNumber);
|
||||
|
||||
if (((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) ||
|
||||
((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, THIS_MODULE, &d)) == 0))
|
||||
goto found;
|
||||
if (bInterfaceNumber == 0) {
|
||||
/* Single-tuner device, or first interface on
|
||||
* multi-tuner device
|
||||
*/
|
||||
|
||||
return ret;
|
||||
if ((ret = dvb_usb_device_init(intf, &megasky_properties,
|
||||
THIS_MODULE, &d)) == 0) {
|
||||
rc_init_seq = megasky_rc_init;
|
||||
goto found;
|
||||
}
|
||||
|
||||
found:
|
||||
if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
|
||||
THIS_MODULE, &d)) == 0) {
|
||||
/* No remote control, so no rc_init_seq */
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* This configures both tuners on the TV Walker Twin */
|
||||
if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
|
||||
THIS_MODULE, &d)) == 0) {
|
||||
rc_init_seq = tvwalkertwin_rc_init;
|
||||
goto found;
|
||||
}
|
||||
|
||||
if ((ret = dvb_usb_device_init(intf, &dposh_properties,
|
||||
THIS_MODULE, &d)) == 0) {
|
||||
/* Remote controller not supported yet. */
|
||||
goto found;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
/* Another interface on a multi-tuner device */
|
||||
|
||||
/* The LifeView TV Walker Twin gets here, but struct
|
||||
* tvwalkertwin_properties already configured both
|
||||
* tuners, so there is nothing for us to do here
|
||||
*/
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
found:
|
||||
alt = usb_altnum_to_altsetting(intf, 1);
|
||||
if (alt == NULL) {
|
||||
deb_rc("No alt found!\n");
|
||||
deb("No alt found!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -478,7 +620,7 @@ found:
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = m9206_init(d)) != 0)
|
||||
if ((ret = m920x_init(d, rc_init_seq)) != 0)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
@ -488,6 +630,12 @@ static struct usb_device_id m920x_table [] = {
|
||||
{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
|
||||
{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
|
||||
USB_PID_MSI_DIGI_VOX_MINI_II) },
|
||||
{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
|
||||
USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD) },
|
||||
{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
|
||||
USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, m920x_table);
|
||||
@ -497,14 +645,14 @@ static struct dvb_usb_device_properties megasky_properties = {
|
||||
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-megasky-02.fw",
|
||||
.download_firmware = m9206_firmware_download,
|
||||
.download_firmware = m920x_firmware_download,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = megasky_rc_keys,
|
||||
.rc_key_map_size = ARRAY_SIZE(megasky_rc_keys),
|
||||
.rc_query = m9206_rc_query,
|
||||
.rc_query = m920x_rc_query,
|
||||
|
||||
.size_of_priv = sizeof(struct m9206_state),
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
@ -513,11 +661,11 @@ static struct dvb_usb_device_properties megasky_properties = {
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
.pid_filter_count = 8,
|
||||
.pid_filter = m9206_pid_filter,
|
||||
.pid_filter_ctrl = m9206_pid_filter_ctrl,
|
||||
.pid_filter = m920x_pid_filter,
|
||||
.pid_filter_ctrl = m920x_pid_filter_ctrl,
|
||||
|
||||
.frontend_attach = megasky_mt352_frontend_attach,
|
||||
.tuner_attach = megasky_qt1010_tuner_attach,
|
||||
.frontend_attach = m920x_mt352_frontend_attach,
|
||||
.tuner_attach = m920x_qt1010_tuner_attach,
|
||||
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
@ -530,7 +678,7 @@ static struct dvb_usb_device_properties megasky_properties = {
|
||||
}
|
||||
},
|
||||
}},
|
||||
.i2c_algo = &m9206_i2c_algo,
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
@ -546,22 +694,22 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
|
||||
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-digivox-02.fw",
|
||||
.download_firmware = m9206_firmware_download,
|
||||
.download_firmware = m920x_firmware_download,
|
||||
|
||||
.size_of_priv = sizeof(struct m9206_state),
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
.pid_filter_count = 8,
|
||||
.pid_filter = m9206_pid_filter,
|
||||
.pid_filter_ctrl = m9206_pid_filter_ctrl,
|
||||
.pid_filter = m920x_pid_filter,
|
||||
.pid_filter_ctrl = m920x_pid_filter_ctrl,
|
||||
|
||||
.frontend_attach = digivox_tda10046_frontend_attach,
|
||||
.tuner_attach = digivox_tda8275_tuner_attach,
|
||||
.frontend_attach = m920x_tda10046_08_frontend_attach,
|
||||
.tuner_attach = m920x_tda8275_60_tuner_attach,
|
||||
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
@ -574,7 +722,7 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
|
||||
}
|
||||
},
|
||||
}},
|
||||
.i2c_algo = &m9206_i2c_algo,
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
@ -585,6 +733,122 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
|
||||
}
|
||||
};
|
||||
|
||||
/* LifeView TV Walker Twin support by Nick Andrew <nick@nick-andrew.net>
|
||||
*
|
||||
* LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A
|
||||
* TDA10046 #0 is located at i2c address 0x08
|
||||
* TDA10046 #1 is located at i2c address 0x0b (presently disabled - not yet working)
|
||||
* TDA8275A #0 is located at i2c address 0x60
|
||||
* TDA8275A #1 is located at i2c address 0x61 (presently disabled - not yet working)
|
||||
*/
|
||||
static struct dvb_usb_device_properties tvwalkertwin_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-tvwalkert.fw",
|
||||
.download_firmware = m920x_firmware_download,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = tvwalkertwin_rc_keys,
|
||||
.rc_key_map_size = ARRAY_SIZE(tvwalkertwin_rc_keys),
|
||||
.rc_query = m920x_rc_query,
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
.pid_filter_count = 8,
|
||||
.pid_filter = m920x_pid_filter,
|
||||
.pid_filter_ctrl = m920x_pid_filter_ctrl,
|
||||
|
||||
.frontend_attach = m920x_tda10046_08_frontend_attach,
|
||||
.tuner_attach = m920x_tda8275_60_tuner_attach,
|
||||
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x81,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 512,
|
||||
}
|
||||
}
|
||||
}},{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
.pid_filter_count = 8,
|
||||
.pid_filter = m920x_pid_filter,
|
||||
.pid_filter_ctrl = m920x_pid_filter_ctrl,
|
||||
|
||||
.frontend_attach = m920x_tda10046_0b_frontend_attach,
|
||||
.tuner_attach = m920x_tda8275_61_tuner_attach,
|
||||
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 512,
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ .name = "LifeView TV Walker Twin DVB-T USB2.0",
|
||||
.cold_ids = { &m920x_table[2], NULL },
|
||||
.warm_ids = { &m920x_table[3], NULL },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties dposh_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-dposh-01.fw",
|
||||
.download_firmware = m920x_firmware_download,
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
/* Hardware pid filters don't work with this device/firmware */
|
||||
|
||||
.frontend_attach = m920x_mt352_frontend_attach,
|
||||
.tuner_attach = m920x_qt1010_tuner_attach,
|
||||
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x81,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 512,
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ .name = "Dposh DVB-T USB2.0",
|
||||
.cold_ids = { &m920x_table[4], NULL },
|
||||
.warm_ids = { &m920x_table[5], NULL },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct usb_driver m920x_driver = {
|
||||
.name = "dvb_usb_m920x",
|
||||
.probe = m920x_probe,
|
||||
@ -615,6 +879,11 @@ module_init (m920x_module_init);
|
||||
module_exit (m920x_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
|
||||
MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x");
|
||||
MODULE_DESCRIPTION("DVB Driver for ULI M920x");
|
||||
MODULE_VERSION("0.1");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
*/
|
||||
|
@ -4,7 +4,7 @@
|
||||
#define DVB_USB_LOG_PREFIX "m920x"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define deb_rc(args...) dprintk(dvb_usb_m920x_debug,0x01,args)
|
||||
#define deb(args...) dprintk(dvb_usb_m920x_debug,0x01,args)
|
||||
|
||||
#define M9206_CORE 0x22
|
||||
#define M9206_RC_STATE 0xff51
|
||||
@ -59,9 +59,18 @@ What any other bits might mean, or how to get the slave's ACK/NACK
|
||||
response to a write, is unknown.
|
||||
*/
|
||||
|
||||
struct m9206_state {
|
||||
struct m920x_state {
|
||||
u16 filters[M9206_MAX_FILTERS];
|
||||
int filtering_enabled;
|
||||
int rep_count;
|
||||
};
|
||||
|
||||
/* Initialisation data for the m920x
|
||||
*/
|
||||
|
||||
struct m920x_inits {
|
||||
u16 address;
|
||||
u8 data;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -204,8 +204,8 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
|
||||
static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
|
||||
struct dvb_diseqc_master_cmd *m)
|
||||
{
|
||||
//struct vp702x_fe_state *st = fe->demodulator_priv;
|
||||
u8 cmd[8];//,ibuf[10];
|
||||
struct vp702x_fe_state *st = fe->demodulator_priv;
|
||||
u8 cmd[8],ibuf[10];
|
||||
memset(cmd,0,8);
|
||||
|
||||
deb_fe("%s\n",__FUNCTION__);
|
||||
@ -218,12 +218,12 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
|
||||
memcpy(&cmd[3], m->msg, m->msg_len);
|
||||
cmd[7] = vp702x_chksum(cmd,0,7);
|
||||
|
||||
// vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
|
||||
vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
|
||||
|
||||
// if (ibuf[2] == 0 && ibuf[3] == 0)
|
||||
// deb_fe("diseqc cmd failed.\n");
|
||||
// else
|
||||
// deb_fe("diseqc cmd succeeded.\n");
|
||||
if (ibuf[2] == 0 && ibuf[3] == 0)
|
||||
deb_fe("diseqc cmd failed.\n");
|
||||
else
|
||||
deb_fe("diseqc cmd succeeded.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -293,12 +293,20 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
|
||||
* but no packets have been transfered.
|
||||
* [2] Sometimes (actually very often) NBPACKETS stays at zero
|
||||
* although one packet has been transfered.
|
||||
* [3] Sometimes (actually rarely), the card gets into an erroneous
|
||||
* mode where it continuously generates interrupts, claiming it
|
||||
* has recieved nbpackets>TS_DMA_PACKETS packets, but no packet
|
||||
* has been transfered. Only a reset seems to solve this
|
||||
*/
|
||||
if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
|
||||
unsigned int i = 0;
|
||||
while (pluto->dma_buf[i] == 0x47)
|
||||
i += 188;
|
||||
nbpackets = i / 188;
|
||||
if (i == 0) {
|
||||
pluto_reset_ts(pluto, 1);
|
||||
dev_printk(KERN_DEBUG, &pluto->pdev->dev, "resetting TS because of invalid packet counter\n");
|
||||
}
|
||||
}
|
||||
|
||||
dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets);
|
||||
|
@ -1246,6 +1246,9 @@ static void vpeirq(unsigned long data)
|
||||
if (!budget->feeding1 || (newdma == olddma))
|
||||
return;
|
||||
|
||||
/* Ensure streamed PCI data is synced to CPU */
|
||||
pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
|
||||
|
||||
#if 0
|
||||
/* track rps1 activity */
|
||||
printk("vpeirq: %02x Event Counter 1 0x%04x\n",
|
||||
@ -2679,8 +2682,8 @@ err_iobuf_vfree_6:
|
||||
err_pci_free_5:
|
||||
pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
|
||||
err_saa71466_vfree_4:
|
||||
if (!av7110->grabbing)
|
||||
saa7146_pgtable_free(pdev, &av7110->pt);
|
||||
if (av7110->grabbing)
|
||||
saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
|
||||
err_i2c_del_3:
|
||||
i2c_del_adapter(&av7110->i2c_adap);
|
||||
err_dvb_unregister_adapter_2:
|
||||
@ -2710,7 +2713,7 @@ static int __devexit av7110_detach(struct saa7146_dev* saa)
|
||||
SAA7146_ISR_CLEAR(saa, MASK_10);
|
||||
msleep(50);
|
||||
tasklet_kill(&av7110->vpe_tasklet);
|
||||
saa7146_pgtable_free(saa->pci, &av7110->pt);
|
||||
saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
|
||||
}
|
||||
av7110_exit_v4l(av7110);
|
||||
|
||||
|
@ -904,7 +904,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
|
||||
band = 1;
|
||||
} else if (tuner_frequency < 200000000) {
|
||||
cp = 6;
|
||||
band = 2;
|
||||
band = 1;
|
||||
} else if (tuner_frequency < 290000000) {
|
||||
cp = 3;
|
||||
band = 2;
|
||||
|
@ -195,6 +195,9 @@ static void vpeirq(unsigned long data)
|
||||
u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
|
||||
u32 count;
|
||||
|
||||
/* Ensure streamed PCI data is synced to CPU */
|
||||
pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
|
||||
|
||||
/* nearest lower position divisible by 188 */
|
||||
newdma -= newdma % 188;
|
||||
|
||||
@ -504,16 +507,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
|
||||
strcpy(budget->i2c_adap.name, budget->card->name);
|
||||
|
||||
if (i2c_add_adapter(&budget->i2c_adap) < 0) {
|
||||
dvb_unregister_adapter(&budget->dvb_adapter);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto err_dvb_unregister;
|
||||
}
|
||||
|
||||
ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
|
||||
|
||||
if (NULL ==
|
||||
(budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) {
|
||||
budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt);
|
||||
if (NULL == budget->grabbing) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
goto err_del_i2c;
|
||||
}
|
||||
|
||||
saa7146_write(dev, PCI_BT_V1, 0x001c0000);
|
||||
@ -526,14 +529,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
|
||||
if (bi->type != BUDGET_FS_ACTIVY)
|
||||
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
|
||||
|
||||
if (budget_register(budget) == 0) {
|
||||
return 0;
|
||||
}
|
||||
err:
|
||||
if (budget_register(budget) == 0)
|
||||
return 0; /* Everything OK */
|
||||
|
||||
/* An error occurred, cleanup resources */
|
||||
saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
|
||||
|
||||
err_del_i2c:
|
||||
i2c_del_adapter(&budget->i2c_adap);
|
||||
|
||||
vfree(budget->grabbing);
|
||||
|
||||
err_dvb_unregister:
|
||||
dvb_unregister_adapter(&budget->dvb_adapter);
|
||||
|
||||
return ret;
|
||||
@ -555,16 +560,14 @@ int ttpci_budget_deinit(struct budget *budget)
|
||||
|
||||
budget_unregister(budget);
|
||||
|
||||
tasklet_kill(&budget->vpe_tasklet);
|
||||
|
||||
saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
|
||||
|
||||
i2c_del_adapter(&budget->i2c_adap);
|
||||
|
||||
dvb_unregister_adapter(&budget->dvb_adapter);
|
||||
|
||||
tasklet_kill(&budget->vpe_tasklet);
|
||||
|
||||
saa7146_pgtable_free(dev->pci, &budget->pt);
|
||||
|
||||
vfree(budget->grabbing);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,14 @@
|
||||
# Multimedia Video device configuration
|
||||
#
|
||||
|
||||
menu "Radio Adapters"
|
||||
menuconfig RADIO_ADAPTERS
|
||||
bool "Radio Adapters"
|
||||
depends on VIDEO_DEV
|
||||
default y
|
||||
---help---
|
||||
Say Y here to enable selecting AM/FM radio adapters.
|
||||
|
||||
if RADIO_ADAPTERS
|
||||
|
||||
config RADIO_CADET
|
||||
tristate "ADS Cadet AM/FM Tuner"
|
||||
@ -328,4 +334,5 @@ config USB_DSBR
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called dsbr100.
|
||||
endmenu
|
||||
|
||||
endif # RADIO_ADAPTERS
|
||||
|
@ -33,6 +33,10 @@
|
||||
|
||||
History:
|
||||
|
||||
Version 0.42:
|
||||
Converted dsbr100 to use video_ioctl2
|
||||
by Douglas Landgraf <dougsland@gmail.com>
|
||||
|
||||
Version 0.41-ac1:
|
||||
Alan Cox: Some cleanups and fixes
|
||||
|
||||
@ -121,8 +125,6 @@ devices, that would be 76 and 91. */
|
||||
static int usb_dsbr100_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id);
|
||||
static void usb_dsbr100_disconnect(struct usb_interface *intf);
|
||||
static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
static int usb_dsbr100_open(struct inode *inode, struct file *file);
|
||||
static int usb_dsbr100_close(struct inode *inode, struct file *file);
|
||||
|
||||
@ -142,26 +144,6 @@ struct dsbr100_device {
|
||||
};
|
||||
|
||||
|
||||
/* File system interface */
|
||||
static const struct file_operations usb_dsbr100_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = usb_dsbr100_open,
|
||||
.release = usb_dsbr100_close,
|
||||
.ioctl = usb_dsbr100_ioctl,
|
||||
.compat_ioctl = v4l_compat_ioctl32,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
/* V4L interface */
|
||||
static struct video_device dsbr100_videodev_template=
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.name = "D-Link DSB-R 100",
|
||||
.type = VID_TYPE_TUNER,
|
||||
.fops = &usb_dsbr100_fops,
|
||||
.release = video_device_release,
|
||||
};
|
||||
|
||||
static struct usb_device_id usb_dsbr100_device_table [] = {
|
||||
{ USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
|
||||
{ } /* Terminating entry */
|
||||
@ -252,37 +234,6 @@ static void dsbr100_getstat(struct dsbr100_device *radio)
|
||||
|
||||
/* USB subsystem interface begins here */
|
||||
|
||||
/* check if the device is present and register with v4l and
|
||||
usb if it is */
|
||||
static int usb_dsbr100_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct dsbr100_device *radio;
|
||||
|
||||
if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
if (!(radio->videodev = video_device_alloc())) {
|
||||
kfree(radio);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(radio->videodev, &dsbr100_videodev_template,
|
||||
sizeof(dsbr100_videodev_template));
|
||||
radio->removed = 0;
|
||||
radio->users = 0;
|
||||
radio->usbdev = interface_to_usbdev(intf);
|
||||
radio->curfreq = FREQ_MIN*FREQ_MUL;
|
||||
video_set_drvdata(radio->videodev, radio);
|
||||
if (video_register_device(radio->videodev, VFL_TYPE_RADIO,
|
||||
radio_nr)) {
|
||||
warn("Could not register video device");
|
||||
video_device_release(radio->videodev);
|
||||
kfree(radio);
|
||||
return -EIO;
|
||||
}
|
||||
usb_set_intfdata(intf, radio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* handle unplugging of the device, release data structures
|
||||
if nothing keeps us from doing it. If something is still
|
||||
keeping us busy, the release callback of v4l will take care
|
||||
@ -307,133 +258,147 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf)
|
||||
}
|
||||
|
||||
|
||||
/* Video for Linux interface */
|
||||
|
||||
static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, void *arg)
|
||||
static int vidioc_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *v)
|
||||
{
|
||||
struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
|
||||
|
||||
if (!radio)
|
||||
return -EIO;
|
||||
|
||||
switch(cmd) {
|
||||
case VIDIOC_QUERYCAP:
|
||||
{
|
||||
struct v4l2_capability *v = arg;
|
||||
memset(v,0,sizeof(*v));
|
||||
strlcpy(v->driver, "dsbr100", sizeof (v->driver));
|
||||
strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card));
|
||||
sprintf(v->bus_info,"ISA");
|
||||
v->version = RADIO_VERSION;
|
||||
v->capabilities = V4L2_CAP_TUNER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_G_TUNER:
|
||||
{
|
||||
struct v4l2_tuner *v = arg;
|
||||
|
||||
if (v->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
dsbr100_getstat(radio);
|
||||
|
||||
memset(v,0,sizeof(*v));
|
||||
strcpy(v->name, "FM");
|
||||
v->type = V4L2_TUNER_RADIO;
|
||||
|
||||
v->rangelow = FREQ_MIN*FREQ_MUL;
|
||||
v->rangehigh = FREQ_MAX*FREQ_MUL;
|
||||
v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
|
||||
v->capability=V4L2_TUNER_CAP_LOW;
|
||||
if(radio->stereo)
|
||||
v->audmode = V4L2_TUNER_MODE_STEREO;
|
||||
else
|
||||
v->audmode = V4L2_TUNER_MODE_MONO;
|
||||
v->signal = 0xFFFF; /* We can't get the signal strength */
|
||||
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_S_TUNER:
|
||||
{
|
||||
struct v4l2_tuner *v = arg;
|
||||
|
||||
if (v->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_S_FREQUENCY:
|
||||
{
|
||||
struct v4l2_frequency *f = arg;
|
||||
|
||||
radio->curfreq = f->frequency;
|
||||
if (dsbr100_setfreq(radio, radio->curfreq)==-1)
|
||||
warn("Set frequency failed");
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_G_FREQUENCY:
|
||||
{
|
||||
struct v4l2_frequency *f = arg;
|
||||
|
||||
f->type = V4L2_TUNER_RADIO;
|
||||
f->frequency = radio->curfreq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_QUERYCTRL:
|
||||
{
|
||||
struct v4l2_queryctrl *qc = arg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
|
||||
if (qc->id && qc->id == radio_qctrl[i].id) {
|
||||
memcpy(qc, &(radio_qctrl[i]),
|
||||
sizeof(*qc));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
case VIDIOC_G_CTRL:
|
||||
{
|
||||
struct v4l2_control *ctrl= arg;
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
ctrl->value=radio->muted;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
case VIDIOC_S_CTRL:
|
||||
{
|
||||
struct v4l2_control *ctrl= arg;
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
if (ctrl->value) {
|
||||
if (dsbr100_stop(radio)==-1)
|
||||
warn("Radio did not respond properly");
|
||||
} else {
|
||||
if (dsbr100_start(radio)==-1)
|
||||
warn("Radio did not respond properly");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
|
||||
usb_dsbr100_do_ioctl);
|
||||
}
|
||||
strlcpy(v->driver, "dsbr100", sizeof(v->driver));
|
||||
strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
|
||||
sprintf(v->bus_info, "ISA");
|
||||
v->version = RADIO_VERSION;
|
||||
v->capabilities = V4L2_CAP_TUNER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static int vidioc_g_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *v)
|
||||
{
|
||||
return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl);
|
||||
struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
|
||||
|
||||
if (v->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
dsbr100_getstat(radio);
|
||||
strcpy(v->name, "FM");
|
||||
v->type = V4L2_TUNER_RADIO;
|
||||
v->rangelow = FREQ_MIN*FREQ_MUL;
|
||||
v->rangehigh = FREQ_MAX*FREQ_MUL;
|
||||
v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
|
||||
v->capability = V4L2_TUNER_CAP_LOW;
|
||||
if(radio->stereo)
|
||||
v->audmode = V4L2_TUNER_MODE_STEREO;
|
||||
else
|
||||
v->audmode = V4L2_TUNER_MODE_MONO;
|
||||
v->signal = 0xffff; /* We can't get the signal strength */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *v)
|
||||
{
|
||||
if (v->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
|
||||
|
||||
radio->curfreq = f->frequency;
|
||||
if (dsbr100_setfreq(radio, radio->curfreq)==-1)
|
||||
warn("Set frequency failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_g_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
|
||||
|
||||
f->type = V4L2_TUNER_RADIO;
|
||||
f->frequency = radio->curfreq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_queryctrl(struct file *file, void *priv,
|
||||
struct v4l2_queryctrl *qc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
|
||||
if (qc->id && qc->id == radio_qctrl[i].id) {
|
||||
memcpy(qc, &(radio_qctrl[i]),
|
||||
sizeof(*qc));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vidioc_g_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
ctrl->value = radio->muted;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vidioc_s_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
if (ctrl->value) {
|
||||
if (dsbr100_stop(radio)==-1)
|
||||
warn("Radio did not respond properly");
|
||||
} else {
|
||||
if (dsbr100_start(radio)==-1)
|
||||
warn("Radio did not respond properly");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vidioc_g_audio(struct file *file, void *priv,
|
||||
struct v4l2_audio *a)
|
||||
{
|
||||
if (a->index > 1)
|
||||
return -EINVAL;
|
||||
|
||||
strcpy(a->name, "Radio");
|
||||
a->capability = V4L2_AUDCAP_STEREO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
|
||||
{
|
||||
*i = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
|
||||
{
|
||||
if (i != 0)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_audio(struct file *file, void *priv,
|
||||
struct v4l2_audio *a)
|
||||
{
|
||||
if (a->index != 0)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_dsbr100_open(struct inode *inode, struct file *file)
|
||||
@ -465,6 +430,68 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* File system interface */
|
||||
static const struct file_operations usb_dsbr100_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = usb_dsbr100_open,
|
||||
.release = usb_dsbr100_close,
|
||||
.ioctl = video_ioctl2,
|
||||
.compat_ioctl = v4l_compat_ioctl32,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
/* V4L2 interface */
|
||||
static struct video_device dsbr100_videodev_template =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.name = "D-Link DSB-R 100",
|
||||
.type = VID_TYPE_TUNER,
|
||||
.fops = &usb_dsbr100_fops,
|
||||
.release = video_device_release,
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_g_tuner = vidioc_g_tuner,
|
||||
.vidioc_s_tuner = vidioc_s_tuner,
|
||||
.vidioc_g_frequency = vidioc_g_frequency,
|
||||
.vidioc_s_frequency = vidioc_s_frequency,
|
||||
.vidioc_queryctrl = vidioc_queryctrl,
|
||||
.vidioc_g_ctrl = vidioc_g_ctrl,
|
||||
.vidioc_s_ctrl = vidioc_s_ctrl,
|
||||
.vidioc_g_audio = vidioc_g_audio,
|
||||
.vidioc_s_audio = vidioc_s_audio,
|
||||
.vidioc_g_input = vidioc_g_input,
|
||||
.vidioc_s_input = vidioc_s_input,
|
||||
};
|
||||
|
||||
/* check if the device is present and register with v4l and
|
||||
usb if it is */
|
||||
static int usb_dsbr100_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct dsbr100_device *radio;
|
||||
|
||||
if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
if (!(radio->videodev = video_device_alloc())) {
|
||||
kfree(radio);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(radio->videodev, &dsbr100_videodev_template,
|
||||
sizeof(dsbr100_videodev_template));
|
||||
radio->removed = 0;
|
||||
radio->users = 0;
|
||||
radio->usbdev = interface_to_usbdev(intf);
|
||||
radio->curfreq = FREQ_MIN*FREQ_MUL;
|
||||
video_set_drvdata(radio->videodev, radio);
|
||||
if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) {
|
||||
warn("Could not register video device");
|
||||
video_device_release(radio->videodev);
|
||||
kfree(radio);
|
||||
return -EIO;
|
||||
}
|
||||
usb_set_intfdata(intf, radio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init dsbr100_init(void)
|
||||
{
|
||||
int retval = usb_register(&usb_dsbr100_driver);
|
||||
|
@ -48,6 +48,25 @@
|
||||
|
||||
#define CADET_VERSION KERNEL_VERSION(0,3,3)
|
||||
|
||||
static struct v4l2_queryctrl radio_qctrl[] = {
|
||||
{
|
||||
.id = V4L2_CID_AUDIO_MUTE,
|
||||
.name = "Mute",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.default_value = 1,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
},{
|
||||
.id = V4L2_CID_AUDIO_VOLUME,
|
||||
.name = "Volume",
|
||||
.minimum = 0,
|
||||
.maximum = 0xff,
|
||||
.step = 1,
|
||||
.default_value = 0xff,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
}
|
||||
};
|
||||
|
||||
static int io=-1; /* default to isapnp activation */
|
||||
static int radio_nr = -1;
|
||||
static int users=0;
|
||||
@ -347,135 +366,165 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int cadet_do_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, void *arg)
|
||||
static int vidioc_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *v)
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case VIDIOC_QUERYCAP:
|
||||
{
|
||||
struct v4l2_capability *cap = arg;
|
||||
memset(cap,0,sizeof(*cap));
|
||||
cap->capabilities =
|
||||
V4L2_CAP_TUNER |
|
||||
V4L2_CAP_READWRITE;
|
||||
cap->version = CADET_VERSION;
|
||||
strcpy(cap->driver, "ADS Cadet");
|
||||
strcpy(cap->card, "ADS Cadet");
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_G_TUNER:
|
||||
{
|
||||
struct v4l2_tuner *t = arg;
|
||||
memset(t,0,sizeof(*t));
|
||||
t->type = V4L2_TUNER_RADIO;
|
||||
switch (t->index)
|
||||
{
|
||||
case 0: strcpy(t->name, "FM");
|
||||
t->capability = V4L2_TUNER_CAP_STEREO;
|
||||
t->rangelow = 1400; /* 87.5 MHz */
|
||||
t->rangehigh = 1728; /* 108.0 MHz */
|
||||
t->rxsubchans=cadet_getstereo();
|
||||
switch (t->rxsubchans){
|
||||
case V4L2_TUNER_SUB_MONO:
|
||||
t->audmode = V4L2_TUNER_MODE_MONO;
|
||||
break;
|
||||
case V4L2_TUNER_SUB_STEREO:
|
||||
t->audmode = V4L2_TUNER_MODE_STEREO;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
case 1: strcpy(t->name, "AM");
|
||||
t->capability = V4L2_TUNER_CAP_LOW;
|
||||
t->rangelow = 8320; /* 520 kHz */
|
||||
t->rangehigh = 26400; /* 1650 kHz */
|
||||
t->rxsubchans = V4L2_TUNER_SUB_MONO;
|
||||
t->audmode = V4L2_TUNER_MODE_MONO;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
t->signal = sigstrength; /* We might need to modify scaling of this */
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_S_TUNER:
|
||||
{
|
||||
struct v4l2_tuner *t = arg;
|
||||
if((t->index != 0)&&(t->index != 1))
|
||||
return -EINVAL;
|
||||
|
||||
curtuner = t->index;
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_G_FREQUENCY:
|
||||
{
|
||||
struct v4l2_frequency *f = arg;
|
||||
memset(f,0,sizeof(*f));
|
||||
f->tuner = curtuner;
|
||||
f->type = V4L2_TUNER_RADIO;
|
||||
f->frequency = cadet_getfreq();
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_S_FREQUENCY:
|
||||
{
|
||||
struct v4l2_frequency *f = arg;
|
||||
if (f->type != V4L2_TUNER_RADIO){
|
||||
return -EINVAL;
|
||||
}
|
||||
if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
cadet_setfreq(f->frequency);
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_G_CTRL:
|
||||
{
|
||||
struct v4l2_control *c = arg;
|
||||
switch (c->id){
|
||||
case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
|
||||
c->value = (cadet_getvol() == 0);
|
||||
break;
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
c->value = cadet_getvol();
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_S_CTRL:
|
||||
{
|
||||
struct v4l2_control *c = arg;
|
||||
switch (c->id){
|
||||
case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
|
||||
if (c->value) cadet_setvol(0);
|
||||
else cadet_setvol(0xffff);
|
||||
break;
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
cadet_setvol(c->value);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
v->capabilities =
|
||||
V4L2_CAP_TUNER |
|
||||
V4L2_CAP_READWRITE;
|
||||
v->version = CADET_VERSION;
|
||||
strcpy(v->driver, "ADS Cadet");
|
||||
strcpy(v->card, "ADS Cadet");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cadet_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static int vidioc_g_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *v)
|
||||
{
|
||||
return video_usercopy(inode, file, cmd, arg, cadet_do_ioctl);
|
||||
v->type = V4L2_TUNER_RADIO;
|
||||
switch (v->index) {
|
||||
case 0:
|
||||
strcpy(v->name, "FM");
|
||||
v->capability = V4L2_TUNER_CAP_STEREO;
|
||||
v->rangelow = 1400; /* 87.5 MHz */
|
||||
v->rangehigh = 1728; /* 108.0 MHz */
|
||||
v->rxsubchans=cadet_getstereo();
|
||||
switch (v->rxsubchans){
|
||||
case V4L2_TUNER_SUB_MONO:
|
||||
v->audmode = V4L2_TUNER_MODE_MONO;
|
||||
break;
|
||||
case V4L2_TUNER_SUB_STEREO:
|
||||
v->audmode = V4L2_TUNER_MODE_STEREO;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
strcpy(v->name, "AM");
|
||||
v->capability = V4L2_TUNER_CAP_LOW;
|
||||
v->rangelow = 8320; /* 520 kHz */
|
||||
v->rangehigh = 26400; /* 1650 kHz */
|
||||
v->rxsubchans = V4L2_TUNER_SUB_MONO;
|
||||
v->audmode = V4L2_TUNER_MODE_MONO;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
v->signal = sigstrength; /* We might need to modify scaling of this */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *v)
|
||||
{
|
||||
if((v->index != 0)&&(v->index != 1))
|
||||
return -EINVAL;
|
||||
curtuner = v->index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_g_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
f->tuner = curtuner;
|
||||
f->type = V4L2_TUNER_RADIO;
|
||||
f->frequency = cadet_getfreq();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int vidioc_s_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
if (f->type != V4L2_TUNER_RADIO)
|
||||
return -EINVAL;
|
||||
if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728)))
|
||||
return -EINVAL;
|
||||
if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400)))
|
||||
return -EINVAL;
|
||||
cadet_setfreq(f->frequency);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_queryctrl(struct file *file, void *priv,
|
||||
struct v4l2_queryctrl *qc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
|
||||
if (qc->id && qc->id == radio_qctrl[i].id) {
|
||||
memcpy(qc, &(radio_qctrl[i]),
|
||||
sizeof(*qc));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vidioc_g_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
switch (ctrl->id){
|
||||
case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
|
||||
ctrl->value = (cadet_getvol() == 0);
|
||||
break;
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
ctrl->value = cadet_getvol();
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
switch (ctrl->id){
|
||||
case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
|
||||
if (ctrl->value)
|
||||
cadet_setvol(0);
|
||||
else
|
||||
cadet_setvol(0xffff);
|
||||
break;
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
cadet_setvol(ctrl->value);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_g_audio(struct file *file, void *priv,
|
||||
struct v4l2_audio *a)
|
||||
{
|
||||
if (a->index > 1)
|
||||
return -EINVAL;
|
||||
strcpy(a->name, "Radio");
|
||||
a->capability = V4L2_AUDCAP_STEREO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
|
||||
{
|
||||
*i = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
|
||||
{
|
||||
if (i != 0)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_audio(struct file *file, void *priv,
|
||||
struct v4l2_audio *a)
|
||||
{
|
||||
if (a->index != 0)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -512,7 +561,7 @@ static const struct file_operations cadet_fops = {
|
||||
.open = cadet_open,
|
||||
.release = cadet_release,
|
||||
.read = cadet_read,
|
||||
.ioctl = cadet_ioctl,
|
||||
.ioctl = video_ioctl2,
|
||||
.poll = cadet_poll,
|
||||
.compat_ioctl = v4l_compat_ioctl32,
|
||||
.llseek = no_llseek,
|
||||
@ -524,6 +573,18 @@ static struct video_device cadet_radio=
|
||||
.name = "Cadet radio",
|
||||
.type = VID_TYPE_TUNER,
|
||||
.fops = &cadet_fops,
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_g_tuner = vidioc_g_tuner,
|
||||
.vidioc_s_tuner = vidioc_s_tuner,
|
||||
.vidioc_g_frequency = vidioc_g_frequency,
|
||||
.vidioc_s_frequency = vidioc_s_frequency,
|
||||
.vidioc_queryctrl = vidioc_queryctrl,
|
||||
.vidioc_g_ctrl = vidioc_g_ctrl,
|
||||
.vidioc_s_ctrl = vidioc_s_ctrl,
|
||||
.vidioc_g_audio = vidioc_g_audio,
|
||||
.vidioc_s_audio = vidioc_s_audio,
|
||||
.vidioc_g_input = vidioc_g_input,
|
||||
.vidioc_s_input = vidioc_s_input,
|
||||
};
|
||||
|
||||
static struct pnp_device_id cadet_pnp_devices[] = {
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-common.h>
|
||||
@ -110,7 +109,6 @@ struct radio_device {
|
||||
muted, /* VIDEO_AUDIO_MUTE */
|
||||
stereo, /* VIDEO_TUNER_STEREO_ON */
|
||||
tuned; /* signal strength (0 or 0xffff) */
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static u32 radio_bits_get(struct radio_device *dev)
|
||||
@ -394,7 +392,6 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
|
||||
}
|
||||
|
||||
radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA;
|
||||
mutex_init(&radio_unit->lock);
|
||||
|
||||
maestro_radio_inst = video_device_alloc();
|
||||
if (maestro_radio_inst == NULL) {
|
||||
|
@ -410,7 +410,6 @@ static struct video_device zoltrix_radio =
|
||||
.owner = THIS_MODULE,
|
||||
.name = "Zoltrix Radio Plus",
|
||||
.type = VID_TYPE_TUNER,
|
||||
.hardware = 0,
|
||||
.fops = &zoltrix_fops,
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_g_tuner = vidioc_g_tuner,
|
||||
|
@ -2,14 +2,19 @@
|
||||
# Multimedia Video device configuration
|
||||
#
|
||||
|
||||
menu "Video Capture Adapters"
|
||||
menuconfig VIDEO_CAPTURE_DRIVERS
|
||||
bool "Video capture adapters"
|
||||
depends on VIDEO_DEV
|
||||
default y
|
||||
---help---
|
||||
Say Y here to enable selecting the video adapters for
|
||||
webcams, analog TV, and hybrid analog/digital TV.
|
||||
Some of those devices also supports FM radio.
|
||||
|
||||
comment "Video Capture Adapters"
|
||||
if VIDEO_CAPTURE_DRIVERS
|
||||
|
||||
config VIDEO_ADV_DEBUG
|
||||
bool "Enable advanced debug functionality"
|
||||
depends on VIDEO_DEV
|
||||
default n
|
||||
---help---
|
||||
Say Y here to enable advanced debugging functionality on some
|
||||
@ -34,7 +39,7 @@ config VIDEO_HELPER_CHIPS_AUTO
|
||||
#
|
||||
|
||||
menu "Encoders/decoders and other helper chips"
|
||||
depends on VIDEO_DEV && !VIDEO_HELPER_CHIPS_AUTO
|
||||
depends on !VIDEO_HELPER_CHIPS_AUTO
|
||||
|
||||
comment "Audio decoders"
|
||||
|
||||
@ -61,7 +66,7 @@ config VIDEO_TDA7432
|
||||
|
||||
config VIDEO_TDA9840
|
||||
tristate "Philips TDA9840 audio processor"
|
||||
depends on VIDEO_DEV && I2C
|
||||
depends on I2C
|
||||
---help---
|
||||
Support for tda9840 audio decoder chip found on some Zoran boards.
|
||||
|
||||
@ -79,7 +84,7 @@ config VIDEO_TDA9875
|
||||
|
||||
config VIDEO_TEA6415C
|
||||
tristate "Philips TEA6415C audio processor"
|
||||
depends on VIDEO_DEV && I2C
|
||||
depends on I2C
|
||||
---help---
|
||||
Support for tea6415c audio decoder chip found on some bt8xx boards.
|
||||
|
||||
@ -88,7 +93,7 @@ config VIDEO_TEA6415C
|
||||
|
||||
config VIDEO_TEA6420
|
||||
tristate "Philips TEA6420 audio processor"
|
||||
depends on VIDEO_DEV && I2C
|
||||
depends on I2C
|
||||
---help---
|
||||
Support for tea6420 audio decoder chip found on some bt8xx boards.
|
||||
|
||||
@ -469,7 +474,7 @@ config VIDEO_SAA5246A
|
||||
|
||||
config VIDEO_SAA5249
|
||||
tristate "SAA5249 Teletext processor"
|
||||
depends on VIDEO_DEV && I2C && VIDEO_V4L2
|
||||
depends on I2C && VIDEO_V4L2
|
||||
help
|
||||
Support for I2C bus based teletext using the SAA5249 chip. At the
|
||||
moment this is only useful on some European WinTV cards.
|
||||
@ -479,7 +484,7 @@ config VIDEO_SAA5249
|
||||
|
||||
config TUNER_3036
|
||||
tristate "SAB3036 tuner"
|
||||
depends on VIDEO_DEV && I2C && VIDEO_V4L1
|
||||
depends on I2C && VIDEO_V4L1
|
||||
help
|
||||
Say Y here to include support for Philips SAB3036 compatible tuners.
|
||||
If in doubt, say N.
|
||||
@ -681,8 +686,12 @@ config VIDEO_CAFE_CCIC
|
||||
# USB Multimedia device configuration
|
||||
#
|
||||
|
||||
menu "V4L USB devices"
|
||||
depends on USB && VIDEO_DEV
|
||||
menuconfig V4L_USB_DRIVERS
|
||||
bool "V4L USB devices"
|
||||
depends on USB
|
||||
default y
|
||||
|
||||
if V4L_USB_DRIVERS
|
||||
|
||||
source "drivers/media/video/pvrusb2/Kconfig"
|
||||
|
||||
@ -707,7 +716,7 @@ config VIDEO_OVCAMCHIP
|
||||
|
||||
config USB_W9968CF
|
||||
tristate "USB W996[87]CF JPEG Dual Mode Camera support"
|
||||
depends on USB && VIDEO_V4L1 && I2C
|
||||
depends on VIDEO_V4L1 && I2C
|
||||
select VIDEO_OVCAMCHIP
|
||||
---help---
|
||||
Say Y here if you want support for cameras based on OV681 or
|
||||
@ -725,7 +734,7 @@ config USB_W9968CF
|
||||
|
||||
config USB_OV511
|
||||
tristate "USB OV511 Camera support"
|
||||
depends on USB && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. See <file:Documentation/video4linux/ov511.txt>
|
||||
@ -736,7 +745,7 @@ config USB_OV511
|
||||
|
||||
config USB_SE401
|
||||
tristate "USB SE401 Camera support"
|
||||
depends on USB && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. See <file:Documentation/video4linux/se401.txt>
|
||||
@ -749,7 +758,7 @@ source "drivers/media/video/sn9c102/Kconfig"
|
||||
|
||||
config USB_STV680
|
||||
tristate "USB STV680 (Pencam) Camera support"
|
||||
depends on USB && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. This includes the Pencam line of cameras.
|
||||
@ -765,7 +774,7 @@ source "drivers/media/video/pwc/Kconfig"
|
||||
|
||||
config USB_ZR364XX
|
||||
tristate "USB ZR364XX Camera support"
|
||||
depends on USB && VIDEO_V4L2
|
||||
depends on VIDEO_V4L2
|
||||
---help---
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port.
|
||||
@ -775,6 +784,6 @@ config USB_ZR364XX
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called zr364xx.
|
||||
|
||||
endmenu # V4L USB devices
|
||||
endif # V4L_USB_DRIVERS
|
||||
|
||||
endmenu
|
||||
endif # VIDEO_CAPTURE_DRIVERS
|
||||
|
@ -555,7 +555,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
|
||||
{
|
||||
struct v4l2_pix_format *pix;
|
||||
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
|
||||
int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC);
|
||||
int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
|
||||
|
||||
switch (fmt->type) {
|
||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||
@ -567,7 +567,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
|
||||
Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
|
||||
Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
|
||||
|
||||
Vlines = pix->height + (is_pal ? 4 : 7);
|
||||
Vlines = pix->height + (is_50Hz ? 4 : 7);
|
||||
|
||||
if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
|
||||
(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <asm/delay.h>
|
||||
|
||||
#include "cx88.h"
|
||||
@ -612,7 +613,7 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board
|
||||
}
|
||||
|
||||
/* Driver asked for hardware access. */
|
||||
int cx8802_request_acquire(struct cx8802_driver *drv)
|
||||
static int cx8802_request_acquire(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx88_core *core = drv->core;
|
||||
|
||||
@ -632,7 +633,7 @@ int cx8802_request_acquire(struct cx8802_driver *drv)
|
||||
}
|
||||
|
||||
/* Driver asked to release hardware. */
|
||||
int cx8802_request_release(struct cx8802_driver *drv)
|
||||
static int cx8802_request_release(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx88_core *core = drv->core;
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "cx88.h"
|
||||
|
@ -111,10 +111,6 @@ static struct i2c_adapter vp3054_i2c_adap_template = {
|
||||
.id = I2C_HW_B_CX2388x,
|
||||
};
|
||||
|
||||
static struct i2c_client vp3054_i2c_client_template = {
|
||||
.name = "VP-3054",
|
||||
};
|
||||
|
||||
int vp3054_i2c_probe(struct cx8802_dev *dev)
|
||||
{
|
||||
struct cx88_core *core = dev->core;
|
||||
@ -133,8 +129,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
|
||||
sizeof(vp3054_i2c->adap));
|
||||
memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
|
||||
sizeof(vp3054_i2c->algo));
|
||||
memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template,
|
||||
sizeof(vp3054_i2c->client));
|
||||
|
||||
vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL;
|
||||
|
||||
@ -144,7 +138,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
|
||||
vp3054_i2c->algo.data = dev;
|
||||
i2c_set_adapdata(&vp3054_i2c->adap, dev);
|
||||
vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
|
||||
vp3054_i2c->client.adapter = &vp3054_i2c->adap;
|
||||
|
||||
vp3054_bit_setscl(dev,1);
|
||||
vp3054_bit_setsda(dev,1);
|
||||
|
@ -26,7 +26,6 @@
|
||||
struct vp3054_i2c_state {
|
||||
struct i2c_adapter adap;
|
||||
struct i2c_algo_bit_data algo;
|
||||
struct i2c_client client;
|
||||
u32 state;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
config VIDEO_EM28XX
|
||||
tristate "Empia EM2800/2820/2840 USB video capture support"
|
||||
depends on VIDEO_V4L1 && USB && I2C
|
||||
depends on VIDEO_V4L1 && I2C
|
||||
select VIDEO_BUF
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_TVEEPROM
|
||||
|
@ -1,6 +1,6 @@
|
||||
config USB_ET61X251
|
||||
tristate "USB ET61X[12]51 PC Camera Controller support"
|
||||
depends on USB && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want support for cameras based on Etoms ET61X151
|
||||
or ET61X251 PC Camera Controllers.
|
||||
|
@ -74,7 +74,7 @@ int ivtv_first_minor = 0;
|
||||
struct ivtv *ivtv_cards[IVTV_MAX_CARDS];
|
||||
|
||||
/* Protects ivtv_cards_active */
|
||||
spinlock_t ivtv_cards_lock = SPIN_LOCK_UNLOCKED;
|
||||
DEFINE_SPINLOCK(ivtv_cards_lock);
|
||||
|
||||
/* add your revision and whatnot here */
|
||||
static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
|
||||
|
@ -804,7 +804,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
|
||||
struct ivtv_open_id *item;
|
||||
struct ivtv *itv = NULL;
|
||||
struct ivtv_stream *s = NULL;
|
||||
int minor = MINOR(inode->i_rdev);
|
||||
int minor = iminor(inode);
|
||||
|
||||
/* Find which card this open was on */
|
||||
spin_lock(&ivtv_cards_lock);
|
||||
|
@ -1,6 +1,6 @@
|
||||
config VIDEO_PVRUSB2
|
||||
tristate "Hauppauge WinTV-PVR USB2 support"
|
||||
depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL
|
||||
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
|
||||
select FW_LOADER
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_TVEEPROM
|
||||
|
@ -391,22 +391,29 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
|
||||
int pvr2_encoder_configure(struct pvr2_hdw *hdw)
|
||||
{
|
||||
int ret;
|
||||
int val;
|
||||
pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
|
||||
" (cx2341x module)");
|
||||
hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
|
||||
hdw->enc_ctl_state.width = hdw->res_hor_val;
|
||||
hdw->enc_ctl_state.height = hdw->res_ver_val;
|
||||
hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur &
|
||||
(V4L2_STD_NTSC|V4L2_STD_PAL_M)) ?
|
||||
hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
|
||||
0 : 1);
|
||||
|
||||
ret = 0;
|
||||
|
||||
ret |= pvr2_encoder_prep_config(hdw);
|
||||
|
||||
/* saa7115: 0xf0 */
|
||||
val = 0xf0;
|
||||
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
|
||||
/* ivtv cx25840: 0x140 */
|
||||
val = 0x140;
|
||||
}
|
||||
|
||||
if (!ret) ret = pvr2_encoder_vcmd(
|
||||
hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
|
||||
0xf0, 0xf0);
|
||||
val, val);
|
||||
|
||||
/* setup firmware to notify us about some events (don't know why...) */
|
||||
if (!ret) ret = pvr2_encoder_vcmd(
|
||||
|
@ -83,7 +83,7 @@ static struct pvr2_string_table pvr2_client_lists[] = {
|
||||
};
|
||||
|
||||
static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
|
||||
static DECLARE_MUTEX(pvr2_unit_sem);
|
||||
static DEFINE_MUTEX(pvr2_unit_mtx);
|
||||
|
||||
static int ctlchg = 0;
|
||||
static int initusbreset = 1;
|
||||
@ -2076,14 +2076,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
|
||||
hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
|
||||
if (!hdw->ctl_read_urb) goto fail;
|
||||
|
||||
down(&pvr2_unit_sem); do {
|
||||
mutex_lock(&pvr2_unit_mtx); do {
|
||||
for (idx = 0; idx < PVR_NUM; idx++) {
|
||||
if (unit_pointers[idx]) continue;
|
||||
hdw->unit_number = idx;
|
||||
unit_pointers[idx] = hdw;
|
||||
break;
|
||||
}
|
||||
} while (0); up(&pvr2_unit_sem);
|
||||
} while (0); mutex_unlock(&pvr2_unit_mtx);
|
||||
|
||||
cnt1 = 0;
|
||||
cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
|
||||
@ -2186,13 +2186,13 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
|
||||
}
|
||||
pvr2_i2c_core_done(hdw);
|
||||
pvr2_hdw_remove_usb_stuff(hdw);
|
||||
down(&pvr2_unit_sem); do {
|
||||
mutex_lock(&pvr2_unit_mtx); do {
|
||||
if ((hdw->unit_number >= 0) &&
|
||||
(hdw->unit_number < PVR_NUM) &&
|
||||
(unit_pointers[hdw->unit_number] == hdw)) {
|
||||
unit_pointers[hdw->unit_number] = NULL;
|
||||
}
|
||||
} while (0); up(&pvr2_unit_sem);
|
||||
} while (0); mutex_unlock(&pvr2_unit_mtx);
|
||||
kfree(hdw->controls);
|
||||
kfree(hdw->mpeg_ctrl_info);
|
||||
kfree(hdw->std_defs);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "pvrusb2-hdw-internal.h"
|
||||
#include "pvrusb2-debug.h"
|
||||
#include "pvrusb2-fx2-cmd.h"
|
||||
#include "pvrusb2.h"
|
||||
|
||||
#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
|
||||
|
||||
@ -38,6 +39,10 @@ static unsigned int i2c_scan = 0;
|
||||
module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
|
||||
|
||||
static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 };
|
||||
module_param_array(ir_mode, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
|
||||
|
||||
static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
|
||||
unsigned int detail,
|
||||
char *buf,unsigned int maxlen);
|
||||
@ -273,6 +278,15 @@ static int i2c_hack_wm8775(struct pvr2_hdw *hdw,
|
||||
return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
|
||||
}
|
||||
|
||||
/* This is an entry point designed to always fail any attempt to perform a
|
||||
transfer. We use this to cause certain I2C addresses to not be
|
||||
probed. */
|
||||
static int i2c_black_hole(struct pvr2_hdw *hdw,
|
||||
u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* This is a special entry point that is entered if an I2C operation is
|
||||
attempted to a cx25840 chip on model 24xxx hardware. This chip can
|
||||
sometimes wedge itself. Worse still, when this happens msp3400 can
|
||||
@ -994,10 +1008,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
|
||||
}
|
||||
|
||||
/* However, deal with various special cases for 24xxx hardware. */
|
||||
if (ir_mode[hdw->unit_number] == 0) {
|
||||
printk(KERN_INFO "%s: IR disabled\n",hdw->name);
|
||||
hdw->i2c_func[0x18] = i2c_black_hole;
|
||||
} else if (ir_mode[hdw->unit_number] == 1) {
|
||||
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
|
||||
hdw->i2c_func[0x18] = i2c_24xxx_ir;
|
||||
}
|
||||
}
|
||||
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
|
||||
hdw->i2c_func[0x1b] = i2c_hack_wm8775;
|
||||
hdw->i2c_func[0x44] = i2c_hack_cx25840;
|
||||
hdw->i2c_func[0x18] = i2c_24xxx_ir;
|
||||
}
|
||||
|
||||
// Configure the adapter and set up everything else related to it.
|
||||
|
@ -518,40 +518,32 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
|
||||
}
|
||||
sfp->item_last = cip;
|
||||
|
||||
cip->attr_name.attr.owner = THIS_MODULE;
|
||||
cip->attr_name.attr.name = "name";
|
||||
cip->attr_name.attr.mode = S_IRUGO;
|
||||
cip->attr_name.show = fp->show_name;
|
||||
|
||||
cip->attr_type.attr.owner = THIS_MODULE;
|
||||
cip->attr_type.attr.name = "type";
|
||||
cip->attr_type.attr.mode = S_IRUGO;
|
||||
cip->attr_type.show = fp->show_type;
|
||||
|
||||
cip->attr_min.attr.owner = THIS_MODULE;
|
||||
cip->attr_min.attr.name = "min_val";
|
||||
cip->attr_min.attr.mode = S_IRUGO;
|
||||
cip->attr_min.show = fp->show_min;
|
||||
|
||||
cip->attr_max.attr.owner = THIS_MODULE;
|
||||
cip->attr_max.attr.name = "max_val";
|
||||
cip->attr_max.attr.mode = S_IRUGO;
|
||||
cip->attr_max.show = fp->show_max;
|
||||
|
||||
cip->attr_val.attr.owner = THIS_MODULE;
|
||||
cip->attr_val.attr.name = "cur_val";
|
||||
cip->attr_val.attr.mode = S_IRUGO;
|
||||
|
||||
cip->attr_custom.attr.owner = THIS_MODULE;
|
||||
cip->attr_custom.attr.name = "custom_val";
|
||||
cip->attr_custom.attr.mode = S_IRUGO;
|
||||
|
||||
cip->attr_enum.attr.owner = THIS_MODULE;
|
||||
cip->attr_enum.attr.name = "enum_val";
|
||||
cip->attr_enum.attr.mode = S_IRUGO;
|
||||
cip->attr_enum.show = fp->show_enum;
|
||||
|
||||
cip->attr_bits.attr.owner = THIS_MODULE;
|
||||
cip->attr_bits.attr.name = "bit_val";
|
||||
cip->attr_bits.attr.mode = S_IRUGO;
|
||||
cip->attr_bits.show = fp->show_bits;
|
||||
@ -616,12 +608,10 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
|
||||
|
||||
dip = kzalloc(sizeof(*dip),GFP_KERNEL);
|
||||
if (!dip) return;
|
||||
dip->attr_debugcmd.attr.owner = THIS_MODULE;
|
||||
dip->attr_debugcmd.attr.name = "debugcmd";
|
||||
dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
|
||||
dip->attr_debugcmd.show = debugcmd_show;
|
||||
dip->attr_debugcmd.store = debugcmd_store;
|
||||
dip->attr_debuginfo.attr.owner = THIS_MODULE;
|
||||
dip->attr_debuginfo.attr.name = "debuginfo";
|
||||
dip->attr_debuginfo.attr.mode = S_IRUGO;
|
||||
dip->attr_debuginfo.show = debuginfo_show;
|
||||
@ -811,7 +801,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
|
||||
return;
|
||||
}
|
||||
|
||||
sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE;
|
||||
sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
|
||||
sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
|
||||
sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
|
||||
@ -825,7 +814,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
|
||||
sfp->v4l_minor_number_created_ok = !0;
|
||||
}
|
||||
|
||||
sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE;
|
||||
sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
|
||||
sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
|
||||
sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
|
||||
@ -839,7 +827,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
|
||||
sfp->v4l_radio_minor_number_created_ok = !0;
|
||||
}
|
||||
|
||||
sfp->attr_unit_number.attr.owner = THIS_MODULE;
|
||||
sfp->attr_unit_number.attr.name = "unit_number";
|
||||
sfp->attr_unit_number.attr.mode = S_IRUGO;
|
||||
sfp->attr_unit_number.show = unit_number_show;
|
||||
@ -852,7 +839,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
|
||||
sfp->unit_number_created_ok = !0;
|
||||
}
|
||||
|
||||
sfp->attr_bus_info.attr.owner = THIS_MODULE;
|
||||
sfp->attr_bus_info.attr.name = "bus_info_str";
|
||||
sfp->attr_bus_info.attr.mode = S_IRUGO;
|
||||
sfp->attr_bus_info.show = bus_info_show;
|
||||
|
@ -1,6 +1,6 @@
|
||||
config USB_PWC
|
||||
tristate "USB Philips Cameras"
|
||||
depends on USB && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
---help---
|
||||
Say Y or M here if you want to use one of these Philips & OEM
|
||||
webcams:
|
||||
|
@ -1170,6 +1170,42 @@ struct saa7134_board saa7134_boards[] = {
|
||||
.amux = LINE2,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_ECS_TVP3XP_4CB6] = {
|
||||
/* Barry Scott <barry.scott@onelan.co.uk> */
|
||||
.name = "Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)",
|
||||
.audio_clock = 0x187de7,
|
||||
.tuner_type = TUNER_PHILIPS_PAL_I,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.inputs = {{
|
||||
.name = name_tv,
|
||||
.vmux = 1,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
},{
|
||||
.name = name_tv_mono,
|
||||
.vmux = 1,
|
||||
.amux = LINE2,
|
||||
.tv = 1,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 3,
|
||||
.amux = LINE1,
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 8,
|
||||
.amux = LINE1,
|
||||
},{
|
||||
.name = "CVid over SVid",
|
||||
.vmux = 0,
|
||||
.amux = LINE1,
|
||||
}},
|
||||
.radio = {
|
||||
.name = name_radio,
|
||||
.amux = LINE2,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_AVACSSMARTTV] = {
|
||||
/* Roman Pszonczenko <romka@kolos.math.uni.lodz.pl> */
|
||||
.name = "AVACS SmartTV",
|
||||
@ -2754,6 +2790,35 @@ struct saa7134_board saa7134_boards[] = {
|
||||
.amux = LINE1,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_KWORLD_DVBT_210] = {
|
||||
.name = "KWorld DVB-T 210",
|
||||
.audio_clock = 0x00187de7,
|
||||
.tuner_type = TUNER_PHILIPS_TDA8290,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.mpeg = SAA7134_MPEG_DVB,
|
||||
.gpiomask = 1 << 21,
|
||||
.inputs = {{
|
||||
.name = name_tv,
|
||||
.vmux = 1,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 3,
|
||||
.amux = LINE1,
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 8,
|
||||
.amux = LINE1,
|
||||
}},
|
||||
.radio = {
|
||||
.name = name_radio,
|
||||
.amux = TV,
|
||||
.gpio = 0x0200000,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_KWORLD_ATSC110] = {
|
||||
.name = "Kworld ATSC110",
|
||||
.audio_clock = 0x00187de7,
|
||||
@ -3407,6 +3472,36 @@ struct saa7134_board saa7134_boards[] = {
|
||||
.gpio = 0x0200000,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_SABRENT_TV_PCB05] = {
|
||||
.name = "Sabrent PCMCIA TV-PCB05",
|
||||
.audio_clock = 0x00187de7,
|
||||
.tuner_type = TUNER_PHILIPS_TDA8290,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.inputs = {{
|
||||
.name = name_tv,
|
||||
.vmux = 1,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 3,
|
||||
.amux = LINE1,
|
||||
},{
|
||||
.name = name_comp2,
|
||||
.vmux = 0,
|
||||
.amux = LINE1,
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 8,
|
||||
.amux = LINE1,
|
||||
}},
|
||||
.mute = {
|
||||
.name = name_mute,
|
||||
.amux = TV,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
|
||||
@ -3515,7 +3610,13 @@ struct pci_device_id saa7134_pci_tbl[] = {
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
.subvendor = 0x5168, /* Animation Technologies (LifeView) */
|
||||
.subdevice = 0x0214, /* Standard PCI, LR214WF */
|
||||
.subdevice = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */
|
||||
.driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
.subvendor = 0x5168, /* Animation Technologies (LifeView) */
|
||||
.subdevice = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */
|
||||
.driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
@ -3687,6 +3788,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
|
||||
.subvendor = 0x1019,
|
||||
.subdevice = 0x4cb5,
|
||||
.driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB5,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
|
||||
.subvendor = 0x1019,
|
||||
.subdevice = 0x4cb6,
|
||||
.driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB6,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
@ -3913,6 +4020,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
|
||||
.subvendor = 0x17de,
|
||||
.subdevice = 0x7201,
|
||||
.driver_data = SAA7134_BOARD_TEVION_DVBT_220RF,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
.subvendor = 0x17de,
|
||||
.subdevice = 0x7250,
|
||||
.driver_data = SAA7134_BOARD_KWORLD_DVBT_210,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
|
||||
@ -4099,6 +4212,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
|
||||
.subvendor = 0x1043,
|
||||
.subdevice = 0x4857,
|
||||
.driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
|
||||
.subvendor = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */
|
||||
.subdevice = 0x2003, /* OEM cardbus */
|
||||
.driver_data = SAA7134_BOARD_SABRENT_TV_PCB05,
|
||||
},{
|
||||
/* --- boards without eeprom + subsystem ID --- */
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
@ -4178,6 +4297,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
|
||||
case SAA7134_BOARD_CINERGY600_MK3:
|
||||
case SAA7134_BOARD_ECS_TVP3XP:
|
||||
case SAA7134_BOARD_ECS_TVP3XP_4CB5:
|
||||
case SAA7134_BOARD_ECS_TVP3XP_4CB6:
|
||||
case SAA7134_BOARD_MD2819:
|
||||
case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
|
||||
case SAA7134_BOARD_KWORLD_XPERT:
|
||||
@ -4426,6 +4546,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_PINNACLE_PCTV_310i:
|
||||
case SAA7134_BOARD_KWORLD_DVBT_210:
|
||||
case SAA7134_BOARD_TEVION_DVBT_220RF:
|
||||
case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
|
||||
case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
|
||||
|
@ -887,6 +887,20 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = {
|
||||
.antenna_switch= 2,
|
||||
.request_firmware = philips_tda1004x_request_firmware
|
||||
};
|
||||
static struct tda1004x_config kworld_dvb_t_210_config = {
|
||||
.demod_address = 0x08,
|
||||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X,
|
||||
.gpio_config = TDA10046_GP11_I,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.i2c_gate = 0x4b,
|
||||
.tuner_address = 0x61,
|
||||
.tuner_config = 2,
|
||||
.antenna_switch= 1,
|
||||
.request_firmware = philips_tda1004x_request_firmware
|
||||
};
|
||||
/* ------------------------------------------------------------------
|
||||
* special case: this card uses saa713x GPIO22 for the mode switch
|
||||
*/
|
||||
@ -1039,6 +1053,9 @@ static int dvb_init(struct saa7134_dev *dev)
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_KWORLD_DVBT_210:
|
||||
configure_tda827x_fe(dev, &kworld_dvb_t_210_config);
|
||||
break;
|
||||
case SAA7134_BOARD_PHILIPS_TIGER:
|
||||
configure_tda827x_fe(dev, &philips_tiger_config);
|
||||
break;
|
||||
|
@ -235,6 +235,9 @@ struct saa7134_format {
|
||||
#define SAA7134_BOARD_AVERMEDIA_M102 110
|
||||
#define SAA7134_BOARD_ASUS_P7131_4871 111
|
||||
#define SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA 112
|
||||
#define SAA7134_BOARD_ECS_TVP3XP_4CB6 113
|
||||
#define SAA7134_BOARD_KWORLD_DVBT_210 114
|
||||
#define SAA7134_BOARD_SABRENT_TV_PCB05 115
|
||||
|
||||
#define SAA7134_MAXBOARDS 8
|
||||
#define SAA7134_INPUT_MAX 8
|
||||
|
@ -1,6 +1,6 @@
|
||||
config USB_SN9C102
|
||||
tristate "USB SN9C1xx PC Camera Controller support"
|
||||
depends on USB && VIDEO_V4L2
|
||||
depends on VIDEO_V4L2
|
||||
---help---
|
||||
Say Y here if you want support for cameras based on SONiX SN9C101,
|
||||
SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
|
||||
|
@ -141,7 +141,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
|
||||
|
||||
void
|
||||
sn9c102_attach_sensor(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor)
|
||||
const struct sn9c102_sensor* sensor)
|
||||
{
|
||||
memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
|
||||
}
|
||||
|
@ -48,8 +48,8 @@
|
||||
#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
|
||||
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
|
||||
#define SN9C102_MODULE_LICENSE "GPL"
|
||||
#define SN9C102_MODULE_VERSION "1:1.39"
|
||||
#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 39)
|
||||
#define SN9C102_MODULE_VERSION "1:1.44"
|
||||
#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 44)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@ -209,38 +209,41 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Write a sequence of count value/register pairs. Returns -1 after the
|
||||
* first failed write, or 0 for no errors.
|
||||
*/
|
||||
Write a sequence of count value/register pairs. Returns -1 after the first
|
||||
failed write, or 0 for no errors.
|
||||
*/
|
||||
int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2],
|
||||
int count)
|
||||
{
|
||||
struct usb_device* udev = cam->usbdev;
|
||||
u8* value = cam->control_buffer; /* Needed for DMA'able memory */
|
||||
u8* buff = cam->control_buffer;
|
||||
int i, res;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
u8 index = valreg[i][1];
|
||||
|
||||
/*
|
||||
* index is a u8, so it must be <256 and can't be out of range.
|
||||
* If we put in a check anyway, gcc annoys us with a warning
|
||||
* that our check is useless. People get all uppity when they
|
||||
* see warnings in the kernel compile.
|
||||
*/
|
||||
index is a u8, so it must be <256 and can't be out of range.
|
||||
If we put in a check anyway, gcc annoys us with a warning
|
||||
hat our check is useless. People get all uppity when they
|
||||
see warnings in the kernel compile.
|
||||
*/
|
||||
|
||||
*buff = valreg[i][0];
|
||||
|
||||
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
|
||||
0x41, index, 0, buff, 1,
|
||||
SN9C102_CTRL_TIMEOUT);
|
||||
|
||||
*value = valreg[i][0];
|
||||
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
0x08, 0x41, index, 0,
|
||||
value, 1, SN9C102_CTRL_TIMEOUT);
|
||||
if (res < 0) {
|
||||
DBG(3, "Failed to write a register (value 0x%02X, "
|
||||
"index 0x%02X, error %d)", *value, index, res);
|
||||
"index 0x%02X, error %d)", *buff, index, res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cam->reg[index] = *value;
|
||||
cam->reg[index] = *buff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -272,8 +275,8 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
|
||||
}
|
||||
|
||||
|
||||
/* NOTE: reading some registers always returns 0 */
|
||||
static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
|
||||
/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
|
||||
int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
|
||||
{
|
||||
struct usb_device* udev = cam->usbdev;
|
||||
u8* buff = cam->control_buffer;
|
||||
@ -299,7 +302,8 @@ int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
|
||||
|
||||
|
||||
static int
|
||||
sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
|
||||
sn9c102_i2c_wait(struct sn9c102_device* cam,
|
||||
const struct sn9c102_sensor* sensor)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
@ -320,7 +324,7 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
|
||||
|
||||
static int
|
||||
sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor)
|
||||
const struct sn9c102_sensor* sensor)
|
||||
{
|
||||
int r , err = 0;
|
||||
|
||||
@ -342,7 +346,7 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
|
||||
|
||||
static int
|
||||
sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor)
|
||||
const struct sn9c102_sensor* sensor)
|
||||
{
|
||||
int r;
|
||||
r = sn9c102_read_reg(cam, 0x08);
|
||||
@ -352,12 +356,12 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
|
||||
|
||||
int
|
||||
sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor, u8 data0, u8 data1,
|
||||
u8 n, u8 buffer[])
|
||||
const struct sn9c102_sensor* sensor, u8 data0,
|
||||
u8 data1, u8 n, u8 buffer[])
|
||||
{
|
||||
struct usb_device* udev = cam->usbdev;
|
||||
u8* data = cam->control_buffer;
|
||||
int err = 0, res;
|
||||
int i = 0, err = 0, res;
|
||||
|
||||
/* Write cycle */
|
||||
data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
|
||||
@ -402,7 +406,8 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
memcpy(buffer, data, sizeof(buffer));
|
||||
for (i = 0; i < n && i < 5; i++)
|
||||
buffer[n-i-1] = data[4-i];
|
||||
|
||||
return (int)data[4];
|
||||
}
|
||||
@ -410,7 +415,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
|
||||
|
||||
int
|
||||
sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor, u8 n, u8 data0,
|
||||
const struct sn9c102_sensor* sensor, u8 n, u8 data0,
|
||||
u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
|
||||
{
|
||||
struct usb_device* udev = cam->usbdev;
|
||||
@ -449,7 +454,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
|
||||
|
||||
int
|
||||
sn9c102_i2c_try_read(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor, u8 address)
|
||||
const struct sn9c102_sensor* sensor, u8 address)
|
||||
{
|
||||
return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
|
||||
address, 1, NULL);
|
||||
@ -458,7 +463,7 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
|
||||
|
||||
int
|
||||
sn9c102_i2c_try_write(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor, u8 address, u8 value)
|
||||
const struct sn9c102_sensor* sensor, u8 address, u8 value)
|
||||
{
|
||||
return sn9c102_i2c_try_raw_write(cam, sensor, 3,
|
||||
sensor->i2c_slave_id, address,
|
||||
@ -657,16 +662,6 @@ sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
|
||||
{
|
||||
static const u8 eoi_marker[2] = {0xff, 0xd9};
|
||||
|
||||
memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker));
|
||||
f->buf.bytesused += sizeof(eoi_marker);
|
||||
}
|
||||
|
||||
|
||||
static void sn9c102_urb_complete(struct urb *urb)
|
||||
{
|
||||
struct sn9c102_device* cam = urb->context;
|
||||
@ -3181,14 +3176,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
|
||||
|
||||
static const struct file_operations sn9c102_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = sn9c102_open,
|
||||
.open = sn9c102_open,
|
||||
.release = sn9c102_release,
|
||||
.ioctl = sn9c102_ioctl,
|
||||
.ioctl = sn9c102_ioctl,
|
||||
.compat_ioctl = v4l_compat_ioctl32,
|
||||
.read = sn9c102_read,
|
||||
.poll = sn9c102_poll,
|
||||
.mmap = sn9c102_mmap,
|
||||
.llseek = no_llseek,
|
||||
.read = sn9c102_read,
|
||||
.poll = sn9c102_poll,
|
||||
.mmap = sn9c102_mmap,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -3251,7 +3246,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; sn9c102_sensor_table[i]; i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
|
||||
err = sn9c102_sensor_table[i](cam);
|
||||
if (!err)
|
||||
break;
|
||||
@ -3262,7 +3257,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
|
||||
DBG(3, "Support for %s maintained by %s",
|
||||
cam->sensor.name, cam->sensor.maintainer);
|
||||
} else {
|
||||
DBG(1, "No supported image sensor detected");
|
||||
DBG(1, "No supported image sensor detected for this bridge");
|
||||
err = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -86,6 +86,8 @@ static const struct usb_device_id sn9c102_id_table[] = {
|
||||
{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), },
|
||||
{ SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), },
|
||||
/* SN9C105 */
|
||||
{ SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
|
||||
{ SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
|
||||
{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
|
||||
{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
|
||||
{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
|
||||
@ -100,6 +102,7 @@ static const struct usb_device_id sn9c102_id_table[] = {
|
||||
{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
|
||||
{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
|
||||
/* SN9C120 */
|
||||
{ SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
|
||||
{ SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), },
|
||||
{ SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
|
||||
{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
|
||||
@ -148,7 +151,6 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
|
||||
&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
|
||||
&sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
|
||||
&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif /* _SN9C102_DEVTABLE_H_ */
|
||||
|
@ -144,7 +144,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor hv7131d = {
|
||||
static const struct sn9c102_sensor hv7131d = {
|
||||
.name = "HV7131D",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
|
||||
@ -248,12 +248,10 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
|
||||
|
||||
err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
|
||||
{0x28, 0x17});
|
||||
if (err)
|
||||
return -EIO;
|
||||
|
||||
r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
|
||||
r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
|
||||
if (r0 < 0 || r1 < 0)
|
||||
if (err || r0 < 0 || r1 < 0)
|
||||
return -EIO;
|
||||
|
||||
if (r0 != 0x00 || r1 != 0x04)
|
||||
|
@ -44,7 +44,6 @@ static int hv7131r_init(struct sn9c102_device* cam)
|
||||
{0xb0, 0x2b}, {0xc0, 0x2c},
|
||||
{0xd0, 0x2d}, {0xe0, 0x2e},
|
||||
{0xf0, 0x2f}, {0xff, 0x30});
|
||||
|
||||
break;
|
||||
case BRIDGE_SN9C105:
|
||||
case BRIDGE_SN9C120:
|
||||
@ -254,7 +253,7 @@ static int hv7131r_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor hv7131r = {
|
||||
static const struct sn9c102_sensor hv7131r = {
|
||||
.name = "HV7131R",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
|
||||
@ -350,11 +349,8 @@ int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
|
||||
{0x34, 0x01}, {0x20, 0x17},
|
||||
{0x34, 0x01}, {0x46, 0x01});
|
||||
|
||||
if (err)
|
||||
return -EIO;
|
||||
|
||||
devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
|
||||
if (devid < 0)
|
||||
if (err || devid < 0)
|
||||
return -EIO;
|
||||
|
||||
if (devid != 0x02)
|
||||
|
@ -55,45 +55,45 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
|
||||
struct v4l2_control* ctrl)
|
||||
{
|
||||
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
|
||||
u8 data[5+1];
|
||||
u8 data[2];
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_EXPOSURE:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[2];
|
||||
ctrl->value = data[0];
|
||||
return 0;
|
||||
case V4L2_CID_GAIN:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
break;
|
||||
case V4L2_CID_HFLIP:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[3] & 0x20 ? 1 : 0;
|
||||
ctrl->value = data[1] & 0x20 ? 1 : 0;
|
||||
return 0;
|
||||
case V4L2_CID_VFLIP:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[3] & 0x80 ? 1 : 0;
|
||||
ctrl->value = data[1] & 0x80 ? 1 : 0;
|
||||
return 0;
|
||||
case V4L2_CID_RED_BALANCE:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
break;
|
||||
case V4L2_CID_BLUE_BALANCE:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
break;
|
||||
case SN9C102_V4L2_CID_GREEN_BALANCE:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
break;
|
||||
default:
|
||||
@ -105,7 +105,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
|
||||
case V4L2_CID_RED_BALANCE:
|
||||
case V4L2_CID_BLUE_BALANCE:
|
||||
case SN9C102_V4L2_CID_GREEN_BALANCE:
|
||||
ctrl->value = data[3] | (data[2] << 8);
|
||||
ctrl->value = data[1] | (data[0] << 8);
|
||||
if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
|
||||
ctrl->value -= 0x10;
|
||||
else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
|
||||
@ -223,7 +223,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor mi0343 = {
|
||||
static const struct sn9c102_sensor mi0343 = {
|
||||
.name = "MI-0343",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
|
||||
@ -332,20 +332,17 @@ static struct sn9c102_sensor mi0343 = {
|
||||
|
||||
int sn9c102_probe_mi0343(struct sn9c102_device* cam)
|
||||
{
|
||||
u8 data[5+1];
|
||||
int err = 0;
|
||||
u8 data[2];
|
||||
|
||||
err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
|
||||
{0x28, 0x17});
|
||||
|
||||
if (err)
|
||||
if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
|
||||
{0x28, 0x17}))
|
||||
return -EIO;
|
||||
|
||||
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
|
||||
2, data) < 0)
|
||||
return -EIO;
|
||||
|
||||
if (data[4] != 0x32 || data[3] != 0xe3)
|
||||
if (data[1] != 0x42 || data[0] != 0xe3)
|
||||
return -ENODEV;
|
||||
|
||||
sn9c102_attach_sensor(cam, &mi0343);
|
||||
|
@ -27,20 +27,105 @@ static int mi0360_init(struct sn9c102_device* cam)
|
||||
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
|
||||
int err = 0;
|
||||
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
|
||||
{0x0a, 0x14}, {0x40, 0x01},
|
||||
{0x20, 0x17}, {0x07, 0x18},
|
||||
{0xa0, 0x19}, {0x02, 0x1c},
|
||||
{0x03, 0x1d}, {0x0f, 0x1e},
|
||||
{0x0c, 0x1f}, {0x00, 0x20},
|
||||
{0x10, 0x21}, {0x20, 0x22},
|
||||
{0x30, 0x23}, {0x40, 0x24},
|
||||
{0x50, 0x25}, {0x60, 0x26},
|
||||
{0x70, 0x27}, {0x80, 0x28},
|
||||
{0x90, 0x29}, {0xa0, 0x2a},
|
||||
{0xb0, 0x2b}, {0xc0, 0x2c},
|
||||
{0xd0, 0x2d}, {0xe0, 0x2e},
|
||||
{0xf0, 0x2f}, {0xff, 0x30});
|
||||
switch (sn9c102_get_bridge(cam)) {
|
||||
case BRIDGE_SN9C103:
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
|
||||
{0x0a, 0x14}, {0x40, 0x01},
|
||||
{0x20, 0x17}, {0x07, 0x18},
|
||||
{0xa0, 0x19}, {0x02, 0x1c},
|
||||
{0x03, 0x1d}, {0x0f, 0x1e},
|
||||
{0x0c, 0x1f}, {0x00, 0x20},
|
||||
{0x10, 0x21}, {0x20, 0x22},
|
||||
{0x30, 0x23}, {0x40, 0x24},
|
||||
{0x50, 0x25}, {0x60, 0x26},
|
||||
{0x70, 0x27}, {0x80, 0x28},
|
||||
{0x90, 0x29}, {0xa0, 0x2a},
|
||||
{0xb0, 0x2b}, {0xc0, 0x2c},
|
||||
{0xd0, 0x2d}, {0xe0, 0x2e},
|
||||
{0xf0, 0x2f}, {0xff, 0x30});
|
||||
break;
|
||||
case BRIDGE_SN9C105:
|
||||
case BRIDGE_SN9C120:
|
||||
err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
|
||||
{0x00, 0x03}, {0x1a, 0x04},
|
||||
{0x50, 0x05}, {0x20, 0x06},
|
||||
{0x10, 0x07}, {0x03, 0x10},
|
||||
{0x08, 0x14}, {0xa2, 0x17},
|
||||
{0x47, 0x18}, {0x00, 0x19},
|
||||
{0x1d, 0x1a}, {0x10, 0x1b},
|
||||
{0x02, 0x1c}, {0x03, 0x1d},
|
||||
{0x0f, 0x1e}, {0x0c, 0x1f},
|
||||
{0x00, 0x20}, {0x29, 0x21},
|
||||
{0x40, 0x22}, {0x54, 0x23},
|
||||
{0x66, 0x24}, {0x76, 0x25},
|
||||
{0x85, 0x26}, {0x94, 0x27},
|
||||
{0xa1, 0x28}, {0xae, 0x29},
|
||||
{0xbb, 0x2a}, {0xc7, 0x2b},
|
||||
{0xd3, 0x2c}, {0xde, 0x2d},
|
||||
{0xea, 0x2e}, {0xf4, 0x2f},
|
||||
{0xff, 0x30}, {0x00, 0x3F},
|
||||
{0xC7, 0x40}, {0x01, 0x41},
|
||||
{0x44, 0x42}, {0x00, 0x43},
|
||||
{0x44, 0x44}, {0x00, 0x45},
|
||||
{0x44, 0x46}, {0x00, 0x47},
|
||||
{0xC7, 0x48}, {0x01, 0x49},
|
||||
{0xC7, 0x4A}, {0x01, 0x4B},
|
||||
{0xC7, 0x4C}, {0x01, 0x4D},
|
||||
{0x44, 0x4E}, {0x00, 0x4F},
|
||||
{0x44, 0x50}, {0x00, 0x51},
|
||||
{0x44, 0x52}, {0x00, 0x53},
|
||||
{0xC7, 0x54}, {0x01, 0x55},
|
||||
{0xC7, 0x56}, {0x01, 0x57},
|
||||
{0xC7, 0x58}, {0x01, 0x59},
|
||||
{0x44, 0x5A}, {0x00, 0x5B},
|
||||
{0x44, 0x5C}, {0x00, 0x5D},
|
||||
{0x44, 0x5E}, {0x00, 0x5F},
|
||||
{0xC7, 0x60}, {0x01, 0x61},
|
||||
{0xC7, 0x62}, {0x01, 0x63},
|
||||
{0xC7, 0x64}, {0x01, 0x65},
|
||||
{0x44, 0x66}, {0x00, 0x67},
|
||||
{0x44, 0x68}, {0x00, 0x69},
|
||||
{0x44, 0x6A}, {0x00, 0x6B},
|
||||
{0xC7, 0x6C}, {0x01, 0x6D},
|
||||
{0xC7, 0x6E}, {0x01, 0x6F},
|
||||
{0xC7, 0x70}, {0x01, 0x71},
|
||||
{0x44, 0x72}, {0x00, 0x73},
|
||||
{0x44, 0x74}, {0x00, 0x75},
|
||||
{0x44, 0x76}, {0x00, 0x77},
|
||||
{0xC7, 0x78}, {0x01, 0x79},
|
||||
{0xC7, 0x7A}, {0x01, 0x7B},
|
||||
{0xC7, 0x7C}, {0x01, 0x7D},
|
||||
{0x44, 0x7E}, {0x00, 0x7F},
|
||||
{0x14, 0x84}, {0x00, 0x85},
|
||||
{0x27, 0x86}, {0x00, 0x87},
|
||||
{0x07, 0x88}, {0x00, 0x89},
|
||||
{0xEC, 0x8A}, {0x0f, 0x8B},
|
||||
{0xD8, 0x8C}, {0x0f, 0x8D},
|
||||
{0x3D, 0x8E}, {0x00, 0x8F},
|
||||
{0x3D, 0x90}, {0x00, 0x91},
|
||||
{0xCD, 0x92}, {0x0f, 0x93},
|
||||
{0xf7, 0x94}, {0x0f, 0x95},
|
||||
{0x0C, 0x96}, {0x00, 0x97},
|
||||
{0x00, 0x98}, {0x66, 0x99},
|
||||
{0x05, 0x9A}, {0x00, 0x9B},
|
||||
{0x04, 0x9C}, {0x00, 0x9D},
|
||||
{0x08, 0x9E}, {0x00, 0x9F},
|
||||
{0x2D, 0xC0}, {0x2D, 0xC1},
|
||||
{0x3A, 0xC2}, {0x05, 0xC3},
|
||||
{0x04, 0xC4}, {0x3F, 0xC5},
|
||||
{0x00, 0xC6}, {0x00, 0xC7},
|
||||
{0x50, 0xC8}, {0x3C, 0xC9},
|
||||
{0x28, 0xCA}, {0xD8, 0xCB},
|
||||
{0x14, 0xCC}, {0xEC, 0xCD},
|
||||
{0x32, 0xCE}, {0xDD, 0xCF},
|
||||
{0x32, 0xD0}, {0xDD, 0xD1},
|
||||
{0x6A, 0xD2}, {0x50, 0xD3},
|
||||
{0x00, 0xD4}, {0x00, 0xD5},
|
||||
{0x00, 0xD6});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
|
||||
0x00, 0x01, 0, 0);
|
||||
@ -65,50 +150,50 @@ static int mi0360_get_ctrl(struct sn9c102_device* cam,
|
||||
struct v4l2_control* ctrl)
|
||||
{
|
||||
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
|
||||
u8 data[5+1];
|
||||
u8 data[2];
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_EXPOSURE:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[2];
|
||||
ctrl->value = data[0];
|
||||
return 0;
|
||||
case V4L2_CID_GAIN:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[3];
|
||||
ctrl->value = data[1];
|
||||
return 0;
|
||||
case V4L2_CID_RED_BALANCE:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[3];
|
||||
ctrl->value = data[1];
|
||||
return 0;
|
||||
case V4L2_CID_BLUE_BALANCE:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[3];
|
||||
ctrl->value = data[1];
|
||||
return 0;
|
||||
case SN9C102_V4L2_CID_GREEN_BALANCE:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[3];
|
||||
ctrl->value = data[1];
|
||||
return 0;
|
||||
case V4L2_CID_HFLIP:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[3] & 0x20 ? 1 : 0;
|
||||
ctrl->value = data[1] & 0x20 ? 1 : 0;
|
||||
return 0;
|
||||
case V4L2_CID_VFLIP:
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
|
||||
2+1, data) < 0)
|
||||
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
|
||||
data) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = data[3] & 0x80 ? 1 : 0;
|
||||
ctrl->value = data[1] & 0x80 ? 1 : 0;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -178,8 +263,19 @@ static int mi0360_set_crop(struct sn9c102_device* cam,
|
||||
{
|
||||
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
|
||||
int err = 0;
|
||||
u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
|
||||
v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
|
||||
u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
|
||||
|
||||
switch (sn9c102_get_bridge(cam)) {
|
||||
case BRIDGE_SN9C103:
|
||||
h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0;
|
||||
break;
|
||||
case BRIDGE_SN9C105:
|
||||
case BRIDGE_SN9C120:
|
||||
h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
err += sn9c102_write_reg(cam, h_start, 0x12);
|
||||
err += sn9c102_write_reg(cam, v_start, 0x13);
|
||||
@ -194,24 +290,30 @@ static int mi0360_set_pix_format(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
|
||||
int err = 0;
|
||||
|
||||
if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
|
||||
err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
|
||||
0x0a, 0x00, 0x02, 0, 0);
|
||||
err += sn9c102_write_reg(cam, 0x20, 0x19);
|
||||
} else {
|
||||
if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
|
||||
err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
|
||||
0x0a, 0x00, 0x05, 0, 0);
|
||||
err += sn9c102_write_reg(cam, 0x60, 0x19);
|
||||
if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
|
||||
sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
|
||||
err += sn9c102_write_reg(cam, 0xa6, 0x17);
|
||||
} else {
|
||||
err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
|
||||
0x0a, 0x00, 0x02, 0, 0);
|
||||
err += sn9c102_write_reg(cam, 0x20, 0x19);
|
||||
if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
|
||||
sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
|
||||
err += sn9c102_write_reg(cam, 0xa2, 0x17);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor mi0360 = {
|
||||
static const struct sn9c102_sensor mi0360 = {
|
||||
.name = "MI-0360",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C103,
|
||||
.supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
|
||||
.frequency = SN9C102_I2C_100KHZ,
|
||||
.interface = SN9C102_I2C_2WIRES,
|
||||
.i2c_slave_id = 0x5d,
|
||||
@ -317,19 +419,31 @@ static struct sn9c102_sensor mi0360 = {
|
||||
|
||||
int sn9c102_probe_mi0360(struct sn9c102_device* cam)
|
||||
{
|
||||
u8 data[5+1];
|
||||
int err;
|
||||
|
||||
err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
|
||||
{0x28, 0x17});
|
||||
if (err)
|
||||
return -EIO;
|
||||
u8 data[2];
|
||||
|
||||
switch (sn9c102_get_bridge(cam)) {
|
||||
case BRIDGE_SN9C103:
|
||||
if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
|
||||
{0x28, 0x17}))
|
||||
return -EIO;
|
||||
break;
|
||||
case BRIDGE_SN9C105:
|
||||
case BRIDGE_SN9C120:
|
||||
if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
|
||||
{0x01, 0x01}, {0x00, 0x01},
|
||||
{0x28, 0x17}))
|
||||
return -EIO;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
|
||||
2+1, data) < 0)
|
||||
2, data) < 0)
|
||||
return -EIO;
|
||||
|
||||
if (data[2] != 0x82 || data[3] != 0x43)
|
||||
if (data[0] != 0x82 || data[1] != 0x43)
|
||||
return -ENODEV;
|
||||
|
||||
sn9c102_attach_sensor(cam, &mi0360);
|
||||
|
@ -29,9 +29,8 @@ static int ov7630_init(struct sn9c102_device* cam)
|
||||
switch (sn9c102_get_bridge(cam)) {
|
||||
case BRIDGE_SN9C101:
|
||||
case BRIDGE_SN9C102:
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x14},
|
||||
{0x60, 0x17}, {0x0f, 0x18},
|
||||
{0x50, 0x19});
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
|
||||
{0x0f, 0x18}, {0x50, 0x19});
|
||||
|
||||
err += sn9c102_i2c_write(cam, 0x12, 0x8d);
|
||||
err += sn9c102_i2c_write(cam, 0x12, 0x0d);
|
||||
@ -61,7 +60,6 @@ static int ov7630_init(struct sn9c102_device* cam)
|
||||
err += sn9c102_i2c_write(cam, 0x71, 0x00);
|
||||
err += sn9c102_i2c_write(cam, 0x74, 0x21);
|
||||
err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
|
||||
|
||||
break;
|
||||
case BRIDGE_SN9C103:
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
|
||||
@ -253,7 +251,7 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor ov7630 = {
|
||||
static const struct sn9c102_sensor ov7630 = {
|
||||
.name = "OV7630",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
|
||||
@ -408,19 +406,16 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
|
||||
switch (sn9c102_get_bridge(cam)) {
|
||||
case BRIDGE_SN9C101:
|
||||
case BRIDGE_SN9C102:
|
||||
err = sn9c102_write_const_regs(cam, {0x01, 0x01},
|
||||
{0x00, 0x01}, {0x28, 0x17});
|
||||
|
||||
err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
|
||||
{0x28, 0x17});
|
||||
break;
|
||||
case BRIDGE_SN9C103: /* do _not_ change anything! */
|
||||
err = sn9c102_write_const_regs(cam, {0x09, 0x01},
|
||||
{0x42, 0x01}, {0x28, 0x17},
|
||||
{0x44, 0x02});
|
||||
err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
|
||||
{0x28, 0x17}, {0x44, 0x02});
|
||||
pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
|
||||
if (err || pid < 0) { /* try a different initialization */
|
||||
err = sn9c102_write_reg(cam, 0x01, 0x01);
|
||||
err += sn9c102_write_reg(cam, 0x00, 0x01);
|
||||
}
|
||||
if (err || pid < 0) /* try a different initialization */
|
||||
err += sn9c102_write_const_regs(cam, {0x01, 0x01},
|
||||
{0x00, 0x01});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -104,8 +104,8 @@ static int ov7660_init(struct sn9c102_device* cam)
|
||||
err += sn9c102_i2c_write(cam, 0x12, 0x80);
|
||||
err += sn9c102_i2c_write(cam, 0x11, 0x09);
|
||||
err += sn9c102_i2c_write(cam, 0x00, 0x0A);
|
||||
err += sn9c102_i2c_write(cam, 0x01, 0x78);
|
||||
err += sn9c102_i2c_write(cam, 0x02, 0x90);
|
||||
err += sn9c102_i2c_write(cam, 0x01, 0x80);
|
||||
err += sn9c102_i2c_write(cam, 0x02, 0x80);
|
||||
err += sn9c102_i2c_write(cam, 0x03, 0x00);
|
||||
err += sn9c102_i2c_write(cam, 0x04, 0x00);
|
||||
err += sn9c102_i2c_write(cam, 0x05, 0x08);
|
||||
@ -122,7 +122,7 @@ static int ov7660_init(struct sn9c102_device* cam)
|
||||
err += sn9c102_i2c_write(cam, 0x10, 0x20);
|
||||
err += sn9c102_i2c_write(cam, 0x11, 0x03);
|
||||
err += sn9c102_i2c_write(cam, 0x12, 0x05);
|
||||
err += sn9c102_i2c_write(cam, 0x13, 0xF8);
|
||||
err += sn9c102_i2c_write(cam, 0x13, 0xC7);
|
||||
err += sn9c102_i2c_write(cam, 0x14, 0x2C);
|
||||
err += sn9c102_i2c_write(cam, 0x15, 0x00);
|
||||
err += sn9c102_i2c_write(cam, 0x16, 0x02);
|
||||
@ -162,7 +162,7 @@ static int ov7660_init(struct sn9c102_device* cam)
|
||||
err += sn9c102_i2c_write(cam, 0x38, 0x02);
|
||||
err += sn9c102_i2c_write(cam, 0x39, 0x43);
|
||||
err += sn9c102_i2c_write(cam, 0x3A, 0x00);
|
||||
err += sn9c102_i2c_write(cam, 0x3B, 0x02);
|
||||
err += sn9c102_i2c_write(cam, 0x3B, 0x0A);
|
||||
err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
|
||||
err += sn9c102_i2c_write(cam, 0x3D, 0x99);
|
||||
err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
|
||||
@ -281,25 +281,34 @@ static int ov7660_get_ctrl(struct sn9c102_device* cam,
|
||||
return -EIO;
|
||||
break;
|
||||
case V4L2_CID_DO_WHITE_BALANCE:
|
||||
ctrl->value = sn9c102_pread_reg(cam, 0x02);
|
||||
if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0)
|
||||
return -EIO;
|
||||
ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
|
||||
break;
|
||||
case V4L2_CID_RED_BALANCE:
|
||||
ctrl->value = sn9c102_pread_reg(cam, 0x05);
|
||||
if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0)
|
||||
return -EIO;
|
||||
ctrl->value &= 0x7f;
|
||||
break;
|
||||
case V4L2_CID_BLUE_BALANCE:
|
||||
ctrl->value = sn9c102_pread_reg(cam, 0x06);
|
||||
if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0)
|
||||
return -EIO;
|
||||
ctrl->value &= 0x7f;
|
||||
break;
|
||||
case SN9C102_V4L2_CID_GREEN_BALANCE:
|
||||
ctrl->value = sn9c102_pread_reg(cam, 0x07);
|
||||
if ((ctrl->value = sn9c102_read_reg(cam, 0x07)) < 0)
|
||||
return -EIO;
|
||||
ctrl->value &= 0x7f;
|
||||
break;
|
||||
case SN9C102_V4L2_CID_BAND_FILTER:
|
||||
if ((ctrl->value = sn9c102_i2c_read(cam, 0x3b)) < 0)
|
||||
return -EIO;
|
||||
ctrl->value &= 0x08;
|
||||
break;
|
||||
case V4L2_CID_GAIN:
|
||||
if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
|
||||
return -EIO;
|
||||
ctrl->value &= 0x7f;
|
||||
ctrl->value &= 0x1f;
|
||||
break;
|
||||
case V4L2_CID_AUTOGAIN:
|
||||
if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
|
||||
@ -335,12 +344,15 @@ static int ov7660_set_ctrl(struct sn9c102_device* cam,
|
||||
case SN9C102_V4L2_CID_GREEN_BALANCE:
|
||||
err += sn9c102_write_reg(cam, ctrl->value, 0x07);
|
||||
break;
|
||||
case SN9C102_V4L2_CID_BAND_FILTER:
|
||||
err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b);
|
||||
break;
|
||||
case V4L2_CID_GAIN:
|
||||
err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
|
||||
err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value);
|
||||
break;
|
||||
case V4L2_CID_AUTOGAIN:
|
||||
err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value |
|
||||
(ctrl->value << 1));
|
||||
err += sn9c102_i2c_write(cam, 0x13, 0xc0 |
|
||||
(ctrl->value * 0x07));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -386,7 +398,7 @@ static int ov7660_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor ov7660 = {
|
||||
static const struct sn9c102_sensor ov7660 = {
|
||||
.name = "OV7660",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
|
||||
@ -401,9 +413,9 @@ static struct sn9c102_sensor ov7660 = {
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "global gain",
|
||||
.minimum = 0x00,
|
||||
.maximum = 0x7f,
|
||||
.maximum = 0x1f,
|
||||
.step = 0x01,
|
||||
.default_value = 0x0a,
|
||||
.default_value = 0x09,
|
||||
.flags = 0,
|
||||
},
|
||||
{
|
||||
@ -413,7 +425,7 @@ static struct sn9c102_sensor ov7660 = {
|
||||
.minimum = 0x00,
|
||||
.maximum = 0xff,
|
||||
.step = 0x01,
|
||||
.default_value = 0x50,
|
||||
.default_value = 0x27,
|
||||
.flags = 0,
|
||||
},
|
||||
{
|
||||
@ -433,7 +445,7 @@ static struct sn9c102_sensor ov7660 = {
|
||||
.minimum = 0x00,
|
||||
.maximum = 0x7f,
|
||||
.step = 0x01,
|
||||
.default_value = 0x1f,
|
||||
.default_value = 0x14,
|
||||
.flags = 0,
|
||||
},
|
||||
{
|
||||
@ -443,7 +455,7 @@ static struct sn9c102_sensor ov7660 = {
|
||||
.minimum = 0x00,
|
||||
.maximum = 0x7f,
|
||||
.step = 0x01,
|
||||
.default_value = 0x1e,
|
||||
.default_value = 0x14,
|
||||
.flags = 0,
|
||||
},
|
||||
{
|
||||
@ -453,7 +465,7 @@ static struct sn9c102_sensor ov7660 = {
|
||||
.minimum = 0x00,
|
||||
.maximum = 0x01,
|
||||
.step = 0x01,
|
||||
.default_value = 0x00,
|
||||
.default_value = 0x01,
|
||||
.flags = 0,
|
||||
},
|
||||
{
|
||||
@ -463,7 +475,17 @@ static struct sn9c102_sensor ov7660 = {
|
||||
.minimum = 0x00,
|
||||
.maximum = 0x7f,
|
||||
.step = 0x01,
|
||||
.default_value = 0x20,
|
||||
.default_value = 0x14,
|
||||
.flags = 0,
|
||||
},
|
||||
{
|
||||
.id = SN9C102_V4L2_CID_BAND_FILTER,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "band filter",
|
||||
.minimum = 0x00,
|
||||
.maximum = 0x01,
|
||||
.step = 0x01,
|
||||
.default_value = 0x00,
|
||||
.flags = 0,
|
||||
},
|
||||
},
|
||||
@ -508,6 +530,7 @@ int sn9c102_probe_ov7660(struct sn9c102_device* cam)
|
||||
return -EIO;
|
||||
if (pid != 0x76 || ver != 0x60)
|
||||
return -ENODEV;
|
||||
|
||||
sn9c102_attach_sensor(cam, &ov7660);
|
||||
|
||||
return 0;
|
||||
|
@ -163,7 +163,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor pas106b = {
|
||||
static const struct sn9c102_sensor pas106b = {
|
||||
.name = "PAS106B",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
|
||||
@ -273,23 +273,21 @@ static struct sn9c102_sensor pas106b = {
|
||||
|
||||
int sn9c102_probe_pas106b(struct sn9c102_device* cam)
|
||||
{
|
||||
int r0 = 0, r1 = 0, err;
|
||||
int r0 = 0, r1 = 0;
|
||||
unsigned int pid = 0;
|
||||
|
||||
/*
|
||||
Minimal initialization to enable the I2C communication
|
||||
NOTE: do NOT change the values!
|
||||
*/
|
||||
err = sn9c102_write_const_regs(cam,
|
||||
{0x01, 0x01}, /* sensor power down */
|
||||
{0x00, 0x01}, /* sensor power on */
|
||||
{0x28, 0x17});/* sensor clock 24 MHz */
|
||||
if (err)
|
||||
if (sn9c102_write_const_regs(cam,
|
||||
{0x01, 0x01}, /* sensor power down */
|
||||
{0x00, 0x01}, /* sensor power on */
|
||||
{0x28, 0x17})) /* sensor clock at 24 MHz */
|
||||
return -EIO;
|
||||
|
||||
r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
|
||||
r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
|
||||
|
||||
if (r0 < 0 || r1 < 0)
|
||||
return -EIO;
|
||||
|
||||
|
@ -35,29 +35,28 @@ static int pas202bcb_init(struct sn9c102_device* cam)
|
||||
switch (sn9c102_get_bridge(cam)) {
|
||||
case BRIDGE_SN9C101:
|
||||
case BRIDGE_SN9C102:
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x10},
|
||||
{0x00, 0x11}, {0x00, 0x14},
|
||||
{0x20, 0x17}, {0x30, 0x19},
|
||||
{0x09, 0x18});
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
|
||||
{0x00, 0x14}, {0x20, 0x17},
|
||||
{0x30, 0x19}, {0x09, 0x18});
|
||||
break;
|
||||
case BRIDGE_SN9C103:
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x02},
|
||||
{0x00, 0x03}, {0x1a, 0x04},
|
||||
{0x20, 0x05}, {0x20, 0x06},
|
||||
{0x20, 0x07}, {0x00, 0x10},
|
||||
{0x00, 0x11}, {0x00, 0x14},
|
||||
{0x20, 0x17}, {0x30, 0x19},
|
||||
{0x09, 0x18}, {0x02, 0x1c},
|
||||
{0x03, 0x1d}, {0x0f, 0x1e},
|
||||
{0x0c, 0x1f}, {0x00, 0x20},
|
||||
{0x10, 0x21}, {0x20, 0x22},
|
||||
{0x30, 0x23}, {0x40, 0x24},
|
||||
{0x50, 0x25}, {0x60, 0x26},
|
||||
{0x70, 0x27}, {0x80, 0x28},
|
||||
{0x90, 0x29}, {0xa0, 0x2a},
|
||||
{0xb0, 0x2b}, {0xc0, 0x2c},
|
||||
{0xd0, 0x2d}, {0xe0, 0x2e},
|
||||
{0xf0, 0x2f}, {0xff, 0x30});
|
||||
err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
|
||||
{0x1a, 0x04}, {0x20, 0x05},
|
||||
{0x20, 0x06}, {0x20, 0x07},
|
||||
{0x00, 0x10}, {0x00, 0x11},
|
||||
{0x00, 0x14}, {0x20, 0x17},
|
||||
{0x30, 0x19}, {0x09, 0x18},
|
||||
{0x02, 0x1c}, {0x03, 0x1d},
|
||||
{0x0f, 0x1e}, {0x0c, 0x1f},
|
||||
{0x00, 0x20}, {0x10, 0x21},
|
||||
{0x20, 0x22}, {0x30, 0x23},
|
||||
{0x40, 0x24}, {0x50, 0x25},
|
||||
{0x60, 0x26}, {0x70, 0x27},
|
||||
{0x80, 0x28}, {0x90, 0x29},
|
||||
{0xa0, 0x2a}, {0xb0, 0x2b},
|
||||
{0xc0, 0x2c}, {0xd0, 0x2d},
|
||||
{0xe0, 0x2e}, {0xf0, 0x2f},
|
||||
{0xff, 0x30});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -197,7 +196,7 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor pas202bcb = {
|
||||
static const struct sn9c102_sensor pas202bcb = {
|
||||
.name = "PAS202BCB",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
|
||||
@ -313,9 +312,8 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
|
||||
{0x28, 0x17});/* clock 24 MHz */
|
||||
break;
|
||||
case BRIDGE_SN9C103: /* do _not_ change anything! */
|
||||
err = sn9c102_write_const_regs(cam, {0x09, 0x01},
|
||||
{0x44, 0x01}, {0x44, 0x02},
|
||||
{0x29, 0x17});
|
||||
err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01},
|
||||
{0x44, 0x02}, {0x29, 0x17});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -22,7 +22,7 @@
|
||||
#define _SN9C102_SENSOR_H_
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/videodev.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/errno.h>
|
||||
@ -74,7 +74,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
|
||||
/* Attach a probed sensor to the camera. */
|
||||
extern void
|
||||
sn9c102_attach_sensor(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor);
|
||||
const struct sn9c102_sensor* sensor);
|
||||
|
||||
/*
|
||||
Read/write routines: they always return -1 on error, 0 or the read value
|
||||
@ -85,10 +85,11 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
|
||||
*/
|
||||
|
||||
/* The "try" I2C I/O versions are used when probing the sensor */
|
||||
extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
|
||||
u8 address, u8 value);
|
||||
extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
|
||||
u8 address);
|
||||
extern int sn9c102_i2c_try_write(struct sn9c102_device*,
|
||||
const struct sn9c102_sensor*, u8 address,
|
||||
u8 value);
|
||||
extern int sn9c102_i2c_try_read(struct sn9c102_device*,
|
||||
const struct sn9c102_sensor*, u8 address);
|
||||
|
||||
/*
|
||||
These must be used if and only if the sensor doesn't implement the standard
|
||||
@ -102,29 +103,31 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
|
||||
byte.
|
||||
*/
|
||||
extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor, u8 n,
|
||||
const struct sn9c102_sensor* sensor, u8 n,
|
||||
u8 data0, u8 data1, u8 data2, u8 data3,
|
||||
u8 data4, u8 data5);
|
||||
extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
|
||||
struct sn9c102_sensor* sensor, u8 data0,
|
||||
u8 data1, u8 n, u8 buffer[]);
|
||||
const struct sn9c102_sensor* sensor,
|
||||
u8 data0, u8 data1, u8 n, u8 buffer[]);
|
||||
|
||||
/* To be used after the sensor struct has been attached to the camera struct */
|
||||
extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
|
||||
extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
|
||||
|
||||
/* I/O on registers in the bridge. Could be used by the sensor methods too */
|
||||
extern int sn9c102_read_reg(struct sn9c102_device*, u16 index);
|
||||
extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
|
||||
extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
|
||||
extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
|
||||
int count);
|
||||
/*
|
||||
* Write multiple registers with constant values. For example:
|
||||
* sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
|
||||
*/
|
||||
#define sn9c102_write_const_regs(device, data...) \
|
||||
({ const static u8 _data[][2] = {data}; \
|
||||
sn9c102_write_regs(device, _data, ARRAY_SIZE(_data)); })
|
||||
Write multiple registers with constant values. For example:
|
||||
sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
|
||||
Register adresses must be < 256.
|
||||
*/
|
||||
#define sn9c102_write_const_regs(sn9c102_device, data...) \
|
||||
({ const static u8 _valreg[][2] = {data}; \
|
||||
sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
@ -88,7 +88,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor tas5110c1b = {
|
||||
static const struct sn9c102_sensor tas5110c1b = {
|
||||
.name = "TAS5110C1B",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
|
||||
|
@ -68,7 +68,7 @@ static int tas5110d_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor tas5110d = {
|
||||
static const struct sn9c102_sensor tas5110d = {
|
||||
.name = "TAS5110D",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
|
||||
|
@ -89,7 +89,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
|
||||
}
|
||||
|
||||
|
||||
static struct sn9c102_sensor tas5130d1b = {
|
||||
static const struct sn9c102_sensor tas5130d1b = {
|
||||
.name = "TAS5130D1B",
|
||||
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
|
||||
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
|
||||
|
@ -3,7 +3,7 @@ config VIDEO_USBVIDEO
|
||||
|
||||
config USB_VICAM
|
||||
tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
|
||||
depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL
|
||||
depends on VIDEO_V4L1 && EXPERIMENTAL
|
||||
select VIDEO_USBVIDEO
|
||||
---help---
|
||||
Say Y here if you have 3com homeconnect camera (vicam).
|
||||
@ -13,7 +13,7 @@ config USB_VICAM
|
||||
|
||||
config USB_IBMCAM
|
||||
tristate "USB IBM (Xirlink) C-it Camera support"
|
||||
depends on USB && VIDEO_DEV && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
select VIDEO_USBVIDEO
|
||||
---help---
|
||||
Say Y here if you want to connect a IBM "C-It" camera, also known as
|
||||
@ -28,7 +28,7 @@ config USB_IBMCAM
|
||||
|
||||
config USB_KONICAWC
|
||||
tristate "USB Konica Webcam support"
|
||||
depends on USB && VIDEO_DEV && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
select VIDEO_USBVIDEO
|
||||
---help---
|
||||
Say Y here if you want support for webcams based on a Konica
|
||||
@ -39,7 +39,7 @@ config USB_KONICAWC
|
||||
|
||||
config USB_QUICKCAM_MESSENGER
|
||||
tristate "USB Logitech Quickcam Messenger"
|
||||
depends on USB && VIDEO_DEV && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
select VIDEO_USBVIDEO
|
||||
---help---
|
||||
Say Y or M here to enable support for the USB Logitech Quickcam
|
||||
|
@ -1,6 +1,6 @@
|
||||
config VIDEO_USBVISION
|
||||
tristate "USB video devices based on Nogatech NT1003/1004/1005"
|
||||
depends on I2C && VIDEO_V4L2 && USB
|
||||
depends on I2C && VIDEO_V4L2
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
|
||||
---help---
|
||||
|
@ -127,7 +127,7 @@ set_v4l_control(struct inode *inode,
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
static int palette2pixelformat[] = {
|
||||
const static unsigned int palette2pixelformat[] = {
|
||||
[VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY,
|
||||
[VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555,
|
||||
[VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565,
|
||||
@ -145,7 +145,7 @@ static int palette2pixelformat[] = {
|
||||
[VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
static unsigned int __attribute_pure__
|
||||
palette_to_pixelformat(unsigned int palette)
|
||||
{
|
||||
if (palette < ARRAY_SIZE(palette2pixelformat))
|
||||
@ -154,8 +154,8 @@ palette_to_pixelformat(unsigned int palette)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
pixelformat_to_palette(int pixelformat)
|
||||
static unsigned int __attribute_const__
|
||||
pixelformat_to_palette(unsigned int pixelformat)
|
||||
{
|
||||
int palette = 0;
|
||||
switch (pixelformat)
|
||||
@ -616,6 +616,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
|
||||
case VIDIOCSPICT: /* set tone controls & partial capture format */
|
||||
{
|
||||
struct video_picture *pict = arg;
|
||||
int mem_err = 0, ovl_err = 0;
|
||||
|
||||
memset(&fbuf2, 0, sizeof(fbuf2));
|
||||
|
||||
set_v4l_control(inode, file,
|
||||
@ -628,33 +630,59 @@ v4l_compat_translate_ioctl(struct inode *inode,
|
||||
V4L2_CID_SATURATION, pict->colour, drv);
|
||||
set_v4l_control(inode, file,
|
||||
V4L2_CID_WHITENESS, pict->whiteness, drv);
|
||||
/*
|
||||
* V4L1 uses this ioctl to set both memory capture and overlay
|
||||
* pixel format, while V4L2 has two different ioctls for this.
|
||||
* Some cards may not support one or the other, and may support
|
||||
* different pixel formats for memory vs overlay.
|
||||
*/
|
||||
|
||||
fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
|
||||
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
|
||||
if (err < 0)
|
||||
/* If VIDIOC_G_FMT failed, then the driver likely doesn't
|
||||
support memory capture. Trying to set the memory capture
|
||||
parameters would be pointless. */
|
||||
if (err < 0) {
|
||||
dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
|
||||
if (fmt2->fmt.pix.pixelformat !=
|
||||
palette_to_pixelformat(pict->palette)) {
|
||||
mem_err = -1000; /* didn't even try */
|
||||
} else if (fmt2->fmt.pix.pixelformat !=
|
||||
palette_to_pixelformat(pict->palette)) {
|
||||
fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
|
||||
pict->palette);
|
||||
err = drv(inode, file, VIDIOC_S_FMT, fmt2);
|
||||
if (err < 0)
|
||||
dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err);
|
||||
mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2);
|
||||
if (mem_err < 0)
|
||||
dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
|
||||
mem_err);
|
||||
}
|
||||
|
||||
err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
|
||||
if (err < 0)
|
||||
/* If VIDIOC_G_FBUF failed, then the driver likely doesn't
|
||||
support overlay. Trying to set the overlay parameters
|
||||
would be quite pointless. */
|
||||
if (err < 0) {
|
||||
dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
|
||||
if (fbuf2.fmt.pixelformat !=
|
||||
palette_to_pixelformat(pict->palette)) {
|
||||
ovl_err = -1000; /* didn't even try */
|
||||
} else if (fbuf2.fmt.pixelformat !=
|
||||
palette_to_pixelformat(pict->palette)) {
|
||||
fbuf2.fmt.pixelformat = palette_to_pixelformat(
|
||||
pict->palette);
|
||||
err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
|
||||
if (err < 0)
|
||||
dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err);
|
||||
err = 0; /* likely fails for non-root */
|
||||
ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
|
||||
if (ovl_err < 0)
|
||||
dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
|
||||
ovl_err);
|
||||
}
|
||||
if (ovl_err < 0 && mem_err < 0)
|
||||
/* ioctl failed, couldn't set either parameter */
|
||||
if (mem_err != -1000) {
|
||||
err = mem_err;
|
||||
} else if (ovl_err == -EPERM) {
|
||||
err = 0;
|
||||
} else {
|
||||
err = ovl_err;
|
||||
}
|
||||
else
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
case VIDIOCGTUNER: /* get tuner information */
|
||||
|
@ -702,9 +702,7 @@ videobuf_qbuf(struct videobuf_queue *q,
|
||||
dprintk(1,"qbuf: memory type is wrong.\n");
|
||||
goto done;
|
||||
}
|
||||
if (buf->state == STATE_QUEUED ||
|
||||
buf->state == STATE_PREPARED ||
|
||||
buf->state == STATE_ACTIVE) {
|
||||
if (buf->state != STATE_NEEDS_INIT && buf->state != STATE_IDLE) {
|
||||
dprintk(1,"qbuf: buffer is already queued or active.\n");
|
||||
goto done;
|
||||
}
|
||||
|
@ -433,13 +433,43 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
|
||||
int ret = -EINVAL;
|
||||
|
||||
if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
|
||||
!(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) {
|
||||
!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
|
||||
v4l_print_ioctl(vfd->name, cmd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
/***********************************************************
|
||||
Handles calls to the obsoleted V4L1 API
|
||||
Due to the nature of VIDIOCGMBUF, each driver that supports
|
||||
V4L1 should implement its own handler for this ioctl.
|
||||
***********************************************************/
|
||||
|
||||
/* --- streaming capture ------------------------------------- */
|
||||
if (cmd == VIDIOCGMBUF) {
|
||||
struct video_mbuf *p=arg;
|
||||
|
||||
memset(p,0,sizeof(p));
|
||||
|
||||
if (!vfd->vidiocgmbuf)
|
||||
return ret;
|
||||
ret=vfd->vidiocgmbuf(file, fh, p);
|
||||
if (!ret)
|
||||
dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
|
||||
p->size, p->frames,
|
||||
(unsigned long)p->offsets);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
All other V4L1 calls are handled by v4l1_compat module.
|
||||
Those calls will be translated into V4L2 calls, and
|
||||
__video_do_ioctl will be called again, with one or more
|
||||
V4L2 ioctls.
|
||||
********************************************************/
|
||||
if (_IOC_TYPE(cmd)=='v')
|
||||
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
|
||||
__video_do_ioctl);
|
||||
#endif
|
||||
|
||||
switch(cmd) {
|
||||
/* --- capabilities ------------------------------------------ */
|
||||
@ -791,24 +821,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
|
||||
ret=vfd->vidioc_overlay(file, fh, *i);
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
/* --- streaming capture ------------------------------------- */
|
||||
case VIDIOCGMBUF:
|
||||
{
|
||||
struct video_mbuf *p=arg;
|
||||
|
||||
memset(p,0,sizeof(p));
|
||||
|
||||
if (!vfd->vidiocgmbuf)
|
||||
break;
|
||||
ret=vfd->vidiocgmbuf(file, fh, p);
|
||||
if (!ret)
|
||||
dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
|
||||
p->size, p->frames,
|
||||
(unsigned long)p->offsets);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case VIDIOC_G_FBUF:
|
||||
{
|
||||
struct v4l2_framebuffer *p=arg;
|
||||
|
@ -1,6 +1,6 @@
|
||||
config USB_ZC0301
|
||||
tristate "USB ZC0301[P] Image Processor and Control Chip support"
|
||||
depends on USB && VIDEO_V4L1
|
||||
depends on VIDEO_V4L1
|
||||
---help---
|
||||
Say Y here if you want support for cameras based on the ZC0301 or
|
||||
ZC0301P Image Processors and Control Chips.
|
||||
|
@ -58,6 +58,7 @@ struct saa7146_pgtable {
|
||||
unsigned long offset;
|
||||
/* used for custom pagetables (used for example by budget dvb cards) */
|
||||
struct scatterlist *slist;
|
||||
int nents;
|
||||
};
|
||||
|
||||
struct saa7146_pci_extension_data {
|
||||
@ -157,6 +158,7 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
|
||||
void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
|
||||
int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
|
||||
char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt);
|
||||
void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt);
|
||||
void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data);
|
||||
int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
|
||||
|
||||
|
@ -216,6 +216,8 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data);
|
||||
extern struct saa7146_use_ops saa7146_video_uops;
|
||||
int saa7146_start_preview(struct saa7146_fh *fh);
|
||||
int saa7146_stop_preview(struct saa7146_fh *fh);
|
||||
int saa7146_video_do_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, void *arg);
|
||||
|
||||
/* from saa7146_vbi.c */
|
||||
extern struct saa7146_use_ops saa7146_vbi_uops;
|
||||
|
Loading…
Reference in New Issue
Block a user