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:
Linus Torvalds 2007-05-11 12:57:16 -07:00
commit 57a44415be
65 changed files with 1609 additions and 871 deletions

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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/

View File

@ -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);

View File

@ -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)
{
/*

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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
*/

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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[] = {

View File

@ -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) {

View File

@ -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,

View File

@ -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

View File

@ -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)) {

View File

@ -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;

View File

@ -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"

View File

@ -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);

View File

@ -26,7 +26,6 @@
struct vp3054_i2c_state {
struct i2c_adapter adap;
struct i2c_algo_bit_data algo;
struct i2c_client client;
u32 state;
};

View File

@ -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

View File

@ -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.

View File

@ -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 = {

View File

@ -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);

View File

@ -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

View File

@ -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(

View File

@ -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);

View File

@ -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.

View File

@ -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;

View File

@ -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:

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)); })
/*****************************************************************************/

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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---

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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;