Merge git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb

* git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (59 commits)
  V4L/DVB (7219): zoran: Fix namespace conflicts with Zoran 'GPIO_MAX' enum
  V4L/DVB (7205): tuner-xc2028 depends on FW_LOADER
  V4L/DVB (7201): cx88-mpeg: Fix race condition in variable access
  V4L/DVB (7200): Fix FM firmware loading
  V4L/DVB (7198): V4L, include ioctl.h in videodev headers
  V4L/DVB (7197): bttv: Fix overlay divide error
  V4L/DVB (7195): xc5000: fix build error when built as module
  V4L/DVB (7194): cx88-mpeg: Allow concurrent access to cx88-mpeg devices
  V4L/DVB (7193): tveeprom: Add proper tuner mapping for hauppauge eeprom id 133
  V4L/DVB (7192): Adds support for Genius TVGo A11MCE
  V4L/DVB (7189): autosuspend support
  V4L/DVB (7188): radio-si470x version 1.0.6
  V4L/DVB (7186): tda10086: make the 22kHz tone for DISEQC a config option
  V4L/DVB (7183): radio-si470x: fix build warning
  V4L/DVB (7180): em28xx: add URB_NO_TRANSFER_DMA_MAP, since urb->transfer_dma is set
  V4L/DVB (7179): Allow more than one em28xx board
  V4L/DVB (7164): em28xx-alsa: Add a missing mutex
  V4L/DVB (7163): em28xx: makes audio settings more stable
  V4L/DVB (7162): em28xx: Fix endian and returns the correct values
  V4L/DVB (7161): em28xx: Fix printing debug values higher than 127
  ...
This commit is contained in:
Linus Torvalds 2008-02-18 15:49:47 -08:00
commit 20ef0f1ad0
61 changed files with 1449 additions and 919 deletions

View File

@ -8,7 +8,7 @@
7 -> Leadtek Winfast USB II (em2800) 7 -> Leadtek Winfast USB II (em2800)
8 -> Kworld USB2800 (em2800) 8 -> Kworld USB2800 (em2800)
9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a] 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a]
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500,2040:6502]
11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
12 -> Kworld PVR TV 2800 RF (em2820/em2840) 12 -> Kworld PVR TV 2800 RF (em2820/em2840)
13 -> Terratec Prodigy XS (em2880) [0ccd:0047] 13 -> Terratec Prodigy XS (em2880) [0ccd:0047]

View File

@ -92,9 +92,9 @@
91 -> AVerMedia A169 B [1461:7360] 91 -> AVerMedia A169 B [1461:7360]
92 -> AVerMedia A169 B1 [1461:6360] 92 -> AVerMedia A169 B1 [1461:6360]
93 -> Medion 7134 Bridge #2 [16be:0005] 93 -> Medion 7134 Bridge #2 [16be:0005]
94 -> LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB [5168:3306,5168:3502,4e42:3502] 94 -> LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB [5168:3306,5168:3502,5168:3307,4e42:3502]
95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138] 95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138]
96 -> Medion Md8800 Quadro [16be:0007,16be:0008] 96 -> Medion Md8800 Quadro [16be:0007,16be:0008,16be:000d]
97 -> LifeView FlyDVB-S /Acorp TV134DS [5168:0300,4e42:0300] 97 -> LifeView FlyDVB-S /Acorp TV134DS [5168:0300,4e42:0300]
98 -> Proteus Pro 2309 [0919:2003] 98 -> Proteus Pro 2309 [0919:2003]
99 -> AVerMedia TV Hybrid A16AR [1461:2c00] 99 -> AVerMedia TV Hybrid A16AR [1461:2c00]
@ -129,3 +129,5 @@
128 -> Beholder BeholdTV Columbus TVFM [0000:5201] 128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093] 129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193] 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022]
132 -> Genius TVGO AM11MCE

View File

@ -25,7 +25,7 @@ modprobe zr364xx debug=X mode=Y
- debug : set to 1 to enable verbose debug messages - debug : set to 1 to enable verbose debug messages
- mode : 0 = 320x240, 1 = 160x120, 2 = 640x480 - mode : 0 = 320x240, 1 = 160x120, 2 = 640x480
You can then use the camera with V4L2 compatible applications, for example Ekiga. You can then use the camera with V4L2 compatible applications, for example Ekiga.
To capture a single image, try this: dd if=/dev/video0 of=test.jpg bs=1 count=1 To capture a single image, try this: dd if=/dev/video0 of=test.jpg bs=1M count=1
links : links :
http://mxhaard.free.fr/ (support for many others cams including some Aiptek PocketDV) http://mxhaard.free.fr/ (support for many others cams including some Aiptek PocketDV)
@ -63,3 +63,5 @@ Vendor Product Distributor Model
0x06d6 0x0034 Trust Powerc@m 750 0x06d6 0x0034 Trust Powerc@m 750
0x0a17 0x0062 Pentax Optio 50L 0x0a17 0x0062 Pentax Optio 50L
0x06d6 0x003b Trust Powerc@m 970Z 0x06d6 0x003b Trust Powerc@m 970Z
0x0a17 0x004e Pentax Optio 50
0x041e 0x405d Creative DiVi CAM 516

View File

@ -25,11 +25,16 @@ config VIDEO_DEV
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called videodev. module will be called videodev.
config VIDEO_V4L2_COMMON
tristate
depends on (I2C || I2C=n) && VIDEO_DEV
default (I2C || I2C=n) && VIDEO_DEV
config VIDEO_V4L1 config VIDEO_V4L1
bool "Enable Video For Linux API 1 (DEPRECATED)" bool "Enable Video For Linux API 1 (DEPRECATED)"
depends on VIDEO_DEV depends on VIDEO_DEV && VIDEO_V4L2_COMMON
default VIDEO_DEV && VIDEO_V4L2_COMMON
select VIDEO_V4L1_COMPAT select VIDEO_V4L1_COMPAT
default y
---help--- ---help---
Enables a compatibility API used by most V4L2 devices to allow Enables a compatibility API used by most V4L2 devices to allow
its usage with legacy applications that supports only V4L1 api. its usage with legacy applications that supports only V4L1 api.
@ -39,7 +44,7 @@ config VIDEO_V4L1
config VIDEO_V4L1_COMPAT config VIDEO_V4L1_COMPAT
bool "Enable Video For Linux API 1 compatible Layer" bool "Enable Video For Linux API 1 compatible Layer"
depends on VIDEO_DEV depends on VIDEO_DEV
default y default VIDEO_DEV
---help--- ---help---
This api were developed to be used at Kernel 2.2 and 2.4, but This api were developed to be used at Kernel 2.2 and 2.4, but
lacks support for several video standards. There are several lacks support for several video standards. There are several
@ -55,8 +60,8 @@ config VIDEO_V4L1_COMPAT
config VIDEO_V4L2 config VIDEO_V4L2
bool bool
depends on VIDEO_DEV depends on VIDEO_DEV && VIDEO_V4L2_COMMON
default y default VIDEO_DEV && VIDEO_V4L2_COMMON
source "drivers/media/video/Kconfig" source "drivers/media/video/Kconfig"
@ -93,7 +98,7 @@ if VIDEO_TUNER_CUSTOMIZE
config TUNER_XC2028 config TUNER_XC2028
tristate "XCeive xc2028/xc3028 tuners" tristate "XCeive xc2028/xc3028 tuners"
depends on I2C depends on I2C && FW_LOADER
default m if VIDEO_TUNER_CUSTOMIZE default m if VIDEO_TUNER_CUSTOMIZE
help help
Say Y here to include support for the xc2028/xc3028 tuners. Say Y here to include support for the xc2028/xc3028 tuners.
@ -180,7 +185,6 @@ config VIDEO_TVEEPROM
config DAB config DAB
boolean "DAB adapters" boolean "DAB adapters"
default y
---help--- ---help---
Allow selecting support for for Digital Audio Broadcasting (DAB) Allow selecting support for for Digital Audio Broadcasting (DAB)
Receiver adapters. Receiver adapters.

View File

@ -4,6 +4,6 @@ config VIDEO_SAA7146
config VIDEO_SAA7146_VV config VIDEO_SAA7146_VV
tristate tristate
depends on VIDEO_DEV depends on VIDEO_V4L2
select VIDEOBUF_DMA_SG select VIDEOBUF_DMA_SG
select VIDEO_SAA7146 select VIDEO_SAA7146

View File

@ -1987,3 +1987,49 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
}; };
EXPORT_SYMBOL_GPL(ir_codes_behold); EXPORT_SYMBOL_GPL(ir_codes_behold);
/*
* Remote control for the Genius TVGO A11MCE
* Adrian Pardini <pardo.bsso@gmail.com>
*/
IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = {
/* Keys 0 to 9 */
[0x48] = KEY_0,
[0x09] = KEY_1,
[0x1d] = KEY_2,
[0x1f] = KEY_3,
[0x19] = KEY_4,
[0x1b] = KEY_5,
[0x11] = KEY_6,
[0x17] = KEY_7,
[0x12] = KEY_8,
[0x16] = KEY_9,
[0x54] = KEY_RECORD, /* recording */
[0x06] = KEY_MUTE, /* mute */
[0x10] = KEY_POWER,
[0x40] = KEY_LAST, /* recall */
[0x4c] = KEY_CHANNELUP, /* channel / program + */
[0x00] = KEY_CHANNELDOWN, /* channel / program - */
[0x0d] = KEY_VOLUMEUP,
[0x15] = KEY_VOLUMEDOWN,
[0x4d] = KEY_OK, /* also labeled as Pause */
[0x1c] = KEY_ZOOM, /* full screen and Stop*/
[0x02] = KEY_MODE, /* AV Source or Rewind*/
[0x04] = KEY_LIST, /* -/-- */
/* small arrows above numbers */
[0x1a] = KEY_NEXT, /* also Fast Forward */
[0x0e] = KEY_PREVIOUS, /* also Rewind */
/* these are in a rather non standard layout and have
an alternate name written */
[0x1e] = KEY_UP, /* Video Setting */
[0x0a] = KEY_DOWN, /* Video Default */
[0x05] = KEY_LEFT, /* Snapshot */
[0x0c] = KEY_RIGHT, /* Hide Panel */
/* Four buttons without label */
[0x49] = KEY_RED,
[0x0b] = KEY_GREEN,
[0x13] = KEY_YELLOW,
[0x50] = KEY_BLUE,
};
EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce);

View File

@ -413,7 +413,6 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
V4L2_FIELD_SEQ_TB, // FIXME: does this really work? V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
sizeof(struct saa7146_buf), sizeof(struct saa7146_buf),
file); file);
mutex_init(&fh->vbi_q.lock);
init_timer(&fh->vbi_read_timeout); init_timer(&fh->vbi_read_timeout);
fh->vbi_read_timeout.function = vbi_read_timeout; fh->vbi_read_timeout.function = vbi_read_timeout;

View File

@ -1417,8 +1417,6 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
sizeof(struct saa7146_buf), sizeof(struct saa7146_buf),
file); file);
mutex_init(&fh->video_q.lock);
return 0; return 0;
} }

View File

@ -75,7 +75,11 @@ EXPORT_SYMBOL(bt878);
#if defined(dprintk) #if defined(dprintk)
#undef dprintk #undef dprintk
#endif #endif
#define dprintk if(bt878_debug) printk #define dprintk(fmt, arg...) \
do { \
if (bt878_debug) \
printk(KERN_DEBUG fmt, ##arg); \
} while (0)
static void bt878_mem_free(struct bt878 *bt) static void bt878_mem_free(struct bt878 *bt)
{ {
@ -154,7 +158,7 @@ static int bt878_make_risc(struct bt878 *bt)
} }
if (bt->line_count > 255) { if (bt->line_count > 255) {
printk("bt878: buffer size error!\n"); printk(KERN_ERR "bt878: buffer size error!\n");
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
@ -285,7 +289,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id)
if (astat & (BT878_ASCERR | BT878_AOCERR)) { if (astat & (BT878_ASCERR | BT878_AOCERR)) {
if (bt878_verbose) { if (bt878_verbose) {
printk("bt878(%d): irq%s%s risc_pc=%08x\n", printk(KERN_INFO
"bt878(%d): irq%s%s risc_pc=%08x\n",
bt->nr, bt->nr,
(astat & BT878_ASCERR) ? " SCERR" : (astat & BT878_ASCERR) ? " SCERR" :
"", "",
@ -295,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id)
} }
if (astat & (BT878_APABORT | BT878_ARIPERR | BT878_APPERR)) { if (astat & (BT878_APABORT | BT878_ARIPERR | BT878_APPERR)) {
if (bt878_verbose) { if (bt878_verbose) {
printk printk(KERN_INFO
("bt878(%d): irq%s%s%s risc_pc=%08x\n", "bt878(%d): irq%s%s%s risc_pc=%08x\n",
bt->nr, bt->nr,
(astat & BT878_APABORT) ? " PABORT" : (astat & BT878_APABORT) ? " PABORT" :
"", "",
@ -308,8 +313,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id)
} }
if (astat & (BT878_AFDSR | BT878_AFTRGT | BT878_AFBUS)) { if (astat & (BT878_AFDSR | BT878_AFTRGT | BT878_AFBUS)) {
if (bt878_verbose) { if (bt878_verbose) {
printk printk(KERN_INFO
("bt878(%d): irq%s%s%s risc_pc=%08x\n", "bt878(%d): irq%s%s%s risc_pc=%08x\n",
bt->nr, bt->nr,
(astat & BT878_AFDSR) ? " FDSR" : "", (astat & BT878_AFDSR) ? " FDSR" : "",
(astat & BT878_AFTRGT) ? " FTRGT" : (astat & BT878_AFTRGT) ? " FTRGT" :
@ -510,7 +515,7 @@ static int __devinit bt878_probe(struct pci_dev *dev,
*/ */
if ((result = bt878_mem_alloc(bt))) { if ((result = bt878_mem_alloc(bt))) {
printk("bt878: failed to allocate memory!\n"); printk(KERN_ERR "bt878: failed to allocate memory!\n");
goto fail2; goto fail2;
} }
@ -536,7 +541,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev)
struct bt878 *bt = pci_get_drvdata(pci_dev); struct bt878 *bt = pci_get_drvdata(pci_dev);
if (bt878_verbose) if (bt878_verbose)
printk("bt878(%d): unloading\n", bt->nr); printk(KERN_INFO "bt878(%d): unloading\n", bt->nr);
/* turn off all capturing, DMA and IRQs */ /* turn off all capturing, DMA and IRQs */
btand(~0x13, BT878_AGPIO_DMA_CTL); btand(~0x13, BT878_AGPIO_DMA_CTL);

View File

@ -144,6 +144,7 @@ static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff)
static struct tda10086_config tda10086_config = { static struct tda10086_config tda10086_config = {
.demod_address = 0x0e, .demod_address = 0x0e,
.invert = 0, .invert = 0,
.diseqc_tone = 1,
}; };
static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)

View File

@ -106,9 +106,12 @@ static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask,
static int tda10086_init(struct dvb_frontend* fe) static int tda10086_init(struct dvb_frontend* fe)
{ {
struct tda10086_state* state = fe->demodulator_priv; struct tda10086_state* state = fe->demodulator_priv;
u8 t22k_off = 0x80;
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
if (state->config->diseqc_tone)
t22k_off = 0;
// reset // reset
tda10086_write_byte(state, 0x00, 0x00); tda10086_write_byte(state, 0x00, 0x00);
msleep(10); msleep(10);
@ -158,7 +161,7 @@ static int tda10086_init(struct dvb_frontend* fe)
tda10086_write_byte(state, 0x3d, 0x80); tda10086_write_byte(state, 0x3d, 0x80);
// setup SEC // setup SEC
tda10086_write_byte(state, 0x36, 0x80); // all SEC off, no 22k tone tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone
tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency
tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // } tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
@ -180,16 +183,20 @@ static void tda10086_diseqc_wait(struct tda10086_state *state)
static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{ {
struct tda10086_state* state = fe->demodulator_priv; struct tda10086_state* state = fe->demodulator_priv;
u8 t22k_off = 0x80;
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
if (state->config->diseqc_tone)
t22k_off = 0;
switch (tone) { switch (tone) {
case SEC_TONE_OFF: case SEC_TONE_OFF:
tda10086_write_byte(state, 0x36, 0x80); tda10086_write_byte(state, 0x36, t22k_off);
break; break;
case SEC_TONE_ON: case SEC_TONE_ON:
tda10086_write_byte(state, 0x36, 0x81); tda10086_write_byte(state, 0x36, 0x01 + t22k_off);
break; break;
} }
@ -202,9 +209,13 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
struct tda10086_state* state = fe->demodulator_priv; struct tda10086_state* state = fe->demodulator_priv;
int i; int i;
u8 oldval; u8 oldval;
u8 t22k_off = 0x80;
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
if (state->config->diseqc_tone)
t22k_off = 0;
if (cmd->msg_len > 6) if (cmd->msg_len > 6)
return -EINVAL; return -EINVAL;
oldval = tda10086_read_byte(state, 0x36); oldval = tda10086_read_byte(state, 0x36);
@ -212,7 +223,8 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
for(i=0; i< cmd->msg_len; i++) { for(i=0; i< cmd->msg_len; i++) {
tda10086_write_byte(state, 0x48+i, cmd->msg[i]); tda10086_write_byte(state, 0x48+i, cmd->msg[i]);
} }
tda10086_write_byte(state, 0x36, 0x88 | ((cmd->msg_len - 1) << 4)); tda10086_write_byte(state, 0x36, (0x08 + t22k_off)
| ((cmd->msg_len - 1) << 4));
tda10086_diseqc_wait(state); tda10086_diseqc_wait(state);
@ -225,16 +237,20 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
{ {
struct tda10086_state* state = fe->demodulator_priv; struct tda10086_state* state = fe->demodulator_priv;
u8 oldval = tda10086_read_byte(state, 0x36); u8 oldval = tda10086_read_byte(state, 0x36);
u8 t22k_off = 0x80;
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
if (state->config->diseqc_tone)
t22k_off = 0;
switch(minicmd) { switch(minicmd) {
case SEC_MINI_A: case SEC_MINI_A:
tda10086_write_byte(state, 0x36, 0x84); tda10086_write_byte(state, 0x36, 0x04 + t22k_off);
break; break;
case SEC_MINI_B: case SEC_MINI_B:
tda10086_write_byte(state, 0x36, 0x86); tda10086_write_byte(state, 0x36, 0x06 + t22k_off);
break; break;
} }

View File

@ -33,6 +33,9 @@ struct tda10086_config
/* does the "inversion" need inverted? */ /* does the "inversion" need inverted? */
u8 invert; u8 invert;
/* do we need the diseqc signal with carrier? */
u8 diseqc_tone;
}; };
#if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE)) #if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE))

View File

@ -171,7 +171,7 @@ int tda18271_read_extended(struct dvb_frontend *fe)
if (ret != 2) if (ret != 2)
tda_err("ERROR: i2c_transfer returned: %d\n", ret); tda_err("ERROR: i2c_transfer returned: %d\n", ret);
for (i = 0; i <= TDA18271_NUM_REGS; i++) { for (i = 0; i < TDA18271_NUM_REGS; i++) {
/* don't update write-only registers */ /* don't update write-only registers */
if ((i != R_EB9) && if ((i != R_EB9) &&
(i != R_EB16) && (i != R_EB16) &&

View File

@ -45,7 +45,8 @@ struct xc5000_config {
/* xc5000 callback command */ /* xc5000 callback command */
#define XC5000_TUNER_RESET 0 #define XC5000_TUNER_RESET 0
#if defined(CONFIG_DVB_TUNER_XC5000) || defined(CONFIG_DVB_TUNER_XC5000_MODULE) #if defined(CONFIG_DVB_TUNER_XC5000) || \
(defined(CONFIG_DVB_TUNER_XC5000_MODULE) && defined(MODULE))
extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, struct i2c_adapter *i2c,
struct xc5000_config *cfg); struct xc5000_config *cfg);

View File

@ -966,6 +966,7 @@ static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x
static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock) static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock)
{ {
int i, n; int i, n;
int progressive = 0;
dprintk(2, "av7110:%p, \n", av7110); dprintk(2, "av7110:%p, \n", av7110);
@ -974,6 +975,14 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len
return -EBUSY; return -EBUSY;
} }
for (i = 0; i < len - 5; i++) {
/* get progressive flag from picture extension */
if (buf[i] == 0x00 && buf[i+1] == 0x00 &&
buf[i+2] == 0x01 && (unsigned char)buf[i+3] == 0xb5 &&
(buf[i+4] & 0xf0) == 0x10)
progressive = buf[i+5] & 0x08;
}
/* setting n always > 1, fixes problems when playing stillframes /* setting n always > 1, fixes problems when playing stillframes
consisting of I- and P-Frames */ consisting of I- and P-Frames */
n = MIN_IFRAME / len + 1; n = MIN_IFRAME / len + 1;
@ -985,7 +994,11 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len
dvb_play(av7110, buf, len, 0, 1); dvb_play(av7110, buf, len, 0, 1);
av7110_ipack_flush(&av7110->ipack[1]); av7110_ipack_flush(&av7110->ipack[1]);
return 0;
if (progressive)
return vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1);
else
return 0;
} }

View File

@ -896,6 +896,7 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBS_CINERGY1200 0x1154 #define SUBID_DVBS_CINERGY1200 0x1154
#define SUBID_DVBS_CYNERGY1200N 0x1155 #define SUBID_DVBS_CYNERGY1200N 0x1155
#define SUBID_DVBS_TV_STAR 0x0014 #define SUBID_DVBS_TV_STAR 0x0014
#define SUBID_DVBS_TV_STAR_PLUS_X4 0x0015
#define SUBID_DVBS_TV_STAR_CI 0x0016 #define SUBID_DVBS_TV_STAR_CI 0x0016
#define SUBID_DVBS_EASYWATCH_1 0x001a #define SUBID_DVBS_EASYWATCH_1 0x001a
#define SUBID_DVBS_EASYWATCH_2 0x001b #define SUBID_DVBS_EASYWATCH_2 0x001b
@ -910,6 +911,7 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBC_CINERGY1200 0x1156 #define SUBID_DVBC_CINERGY1200 0x1156
#define SUBID_DVBC_CINERGY1200_MK3 0x1176 #define SUBID_DVBC_CINERGY1200_MK3 0x1176
#define SUBID_DVBT_EASYWATCH 0x003a
#define SUBID_DVBT_KNC1_PLUS 0x0031 #define SUBID_DVBT_KNC1_PLUS 0x0031
#define SUBID_DVBT_KNC1 0x0030 #define SUBID_DVBT_KNC1 0x0030
#define SUBID_DVBT_CINERGY1200 0x1157 #define SUBID_DVBT_CINERGY1200 0x1157
@ -957,6 +959,7 @@ static void frontend_init(struct budget_av *budget_av)
break; break;
case SUBID_DVBS_TV_STAR: case SUBID_DVBS_TV_STAR:
case SUBID_DVBS_TV_STAR_PLUS_X4:
case SUBID_DVBS_TV_STAR_CI: case SUBID_DVBS_TV_STAR_CI:
case SUBID_DVBS_CYNERGY1200N: case SUBID_DVBS_CYNERGY1200N:
case SUBID_DVBS_EASYWATCH: case SUBID_DVBS_EASYWATCH:
@ -1018,6 +1021,7 @@ static void frontend_init(struct budget_av *budget_av)
} }
break; break;
case SUBID_DVBT_EASYWATCH:
case SUBID_DVBT_KNC1: case SUBID_DVBT_KNC1:
case SUBID_DVBT_KNC1_PLUS: case SUBID_DVBT_KNC1_PLUS:
case SUBID_DVBT_CINERGY1200: case SUBID_DVBT_CINERGY1200:
@ -1248,7 +1252,9 @@ MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S); MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S);
MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP); MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3); MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3);
MAKE_BUDGET_INFO(satewt, "Satelco EasyWatch DVB-T", BUDGET_KNC1T);
MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3); MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3); MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
@ -1266,12 +1272,14 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011), MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011), MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014), MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015),
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b), MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),
MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a), MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c), MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c),
MAKE_EXTENSION_PCI(satewt, 0x1894, 0x003a),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022), MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),

View File

@ -351,6 +351,7 @@ static struct s5h1420_config s5h1420_config = {
static struct tda10086_config tda10086_config = { static struct tda10086_config tda10086_config = {
.demod_address = 0x0e, .demod_address = 0x0e,
.invert = 0, .invert = 0,
.diseqc_tone = 1,
}; };
static u8 read_pwm(struct budget* budget) static u8 read_pwm(struct budget* budget)

View File

@ -4,12 +4,12 @@
menuconfig RADIO_ADAPTERS menuconfig RADIO_ADAPTERS
bool "Radio Adapters" bool "Radio Adapters"
depends on VIDEO_DEV depends on VIDEO_V4L2
default y default y
---help--- ---help---
Say Y here to enable selecting AM/FM radio adapters. Say Y here to enable selecting AM/FM radio adapters.
if RADIO_ADAPTERS && VIDEO_DEV if RADIO_ADAPTERS && VIDEO_V4L2
config RADIO_CADET config RADIO_CADET
tristate "ADS Cadet AM/FM Tuner" tristate "ADS Cadet AM/FM Tuner"

View File

@ -361,6 +361,7 @@ static int __init fmi_init(void)
} }
if (!request_region(io, 2, "radio-sf16fmi")) { if (!request_region(io, 2, "radio-sf16fmi")) {
printk(KERN_ERR "radio-sf16fmi: port 0x%x already in use\n", io); printk(KERN_ERR "radio-sf16fmi: port 0x%x already in use\n", io);
pnp_device_detach(dev);
return -EBUSY; return -EBUSY;
} }

View File

@ -470,9 +470,8 @@ static int __init fmr2_init(void)
mutex_init(&lock); mutex_init(&lock);
if (request_region(io, 2, "sf16fmr2")) if (!request_region(io, 2, "sf16fmr2")) {
{ printk(KERN_ERR "radio-sf16fmr2: request_region failed!\n");
printk(KERN_ERR "fmr2: port 0x%x already in use\n", io);
return -EBUSY; return -EBUSY;
} }

View File

@ -62,6 +62,29 @@
* - code cleaned of unnecessary rds_commands * - code cleaned of unnecessary rds_commands
* - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified
* (thanks to Guillaume RAMOUSSE) * (thanks to Guillaume RAMOUSSE)
* 2008-01-27 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.5
* - number of seek_retries changed to tune_timeout
* - fixed problem with incomplete tune operations by own buffers
* - optimization of variables and printf types
* - improved error logging
* 2008-01-31 Tobias Lorenz <tobias.lorenz@gmx.net>
* Oliver Neukum <oliver@neukum.org>
* Version 1.0.6
* - fixed coverity checker warnings in *_usb_driver_disconnect
* - probe()/open() race by correct ordering in probe()
* - DMA coherency rules by separate allocation of all buffers
* - use of endianness macros
* - abuse of spinlock, replaced by mutex
* - racy handling of timer in disconnect,
* replaced by delayed_work
* - racy interruptible_sleep_on(),
* replaced with wait_event_interruptible()
* - handle signals in read()
* 2008-02-08 Tobias Lorenz <tobias.lorenz@gmx.net>
* Oliver Neukum <oliver@neukum.org>
* Version 1.0.7
* - usb autosuspend support
* *
* ToDo: * ToDo:
* - add seeking support * - add seeking support
@ -74,9 +97,10 @@
/* driver definitions */ /* driver definitions */
#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
#define DRIVER_NAME "radio-si470x" #define DRIVER_NAME "radio-si470x"
#define DRIVER_VERSION KERNEL_VERSION(1, 0, 4) #define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6)
#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
#define DRIVER_VERSION "1.0.6"
/* kernel includes */ /* kernel includes */
@ -89,8 +113,10 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/mutex.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/rds.h> #include <media/rds.h>
#include <asm/unaligned.h>
/* USB Device ID List */ /* USB Device ID List */
@ -119,56 +145,56 @@ MODULE_PARM_DESC(radio_nr, "Radio Nr");
/* 0: 200 kHz (USA, Australia) */ /* 0: 200 kHz (USA, Australia) */
/* 1: 100 kHz (Europe, Japan) */ /* 1: 100 kHz (Europe, Japan) */
/* 2: 50 kHz */ /* 2: 50 kHz */
static int space = 2; static unsigned short space = 2;
module_param(space, int, 0); module_param(space, ushort, 0);
MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
/* Bottom of Band (MHz) */ /* Bottom of Band (MHz) */
/* 0: 87.5 - 108 MHz (USA, Europe)*/ /* 0: 87.5 - 108 MHz (USA, Europe)*/
/* 1: 76 - 108 MHz (Japan wide band) */ /* 1: 76 - 108 MHz (Japan wide band) */
/* 2: 76 - 90 MHz (Japan) */ /* 2: 76 - 90 MHz (Japan) */
static int band = 1; static unsigned short band = 1;
module_param(band, int, 0); module_param(band, ushort, 0);
MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
/* De-emphasis */ /* De-emphasis */
/* 0: 75 us (USA) */ /* 0: 75 us (USA) */
/* 1: 50 us (Europe, Australia, Japan) */ /* 1: 50 us (Europe, Australia, Japan) */
static int de = 1; static unsigned short de = 1;
module_param(de, int, 0); module_param(de, ushort, 0);
MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*"); MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*");
/* USB timeout */ /* USB timeout */
static int usb_timeout = 500; static unsigned int usb_timeout = 500;
module_param(usb_timeout, int, 0); module_param(usb_timeout, uint, 0);
MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");
/* Seek retries */ /* Tune timeout */
static int seek_retries = 100; static unsigned int tune_timeout = 3000;
module_param(seek_retries, int, 0); module_param(tune_timeout, uint, 0);
MODULE_PARM_DESC(seek_retries, "Seek retries: *100*"); MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
/* RDS buffer blocks */ /* RDS buffer blocks */
static int rds_buf = 100; static unsigned int rds_buf = 100;
module_param(rds_buf, int, 0); module_param(rds_buf, uint, 0);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
/* RDS maximum block errors */ /* RDS maximum block errors */
static int max_rds_errors = 1; static unsigned short max_rds_errors = 1;
/* 0 means 0 errors requiring correction */ /* 0 means 0 errors requiring correction */
/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ /* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */
/* 2 means 3-5 errors requiring correction */ /* 2 means 3-5 errors requiring correction */
/* 3 means 6+ errors or errors in checkword, correction not possible */ /* 3 means 6+ errors or errors in checkword, correction not possible */
module_param(max_rds_errors, int, 0); module_param(max_rds_errors, ushort, 0);
MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
/* RDS poll frequency */ /* RDS poll frequency */
static int rds_poll_time = 40; static unsigned int rds_poll_time = 40;
/* 40 is used by the original USBRadio.exe */ /* 40 is used by the original USBRadio.exe */
/* 50 is used by radio-cadet */ /* 50 is used by radio-cadet */
/* 75 should be okay */ /* 75 should be okay */
/* 80 is the usual RDS receive interval */ /* 80 is the usual RDS receive interval */
module_param(rds_poll_time, int, 0); module_param(rds_poll_time, uint, 0);
MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
@ -393,22 +419,19 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
struct si470x_device { struct si470x_device {
/* reference to USB and video device */ /* reference to USB and video device */
struct usb_device *usbdev; struct usb_device *usbdev;
struct usb_interface *intf;
struct video_device *videodev; struct video_device *videodev;
/* are these really necessary ? */ /* driver management */
int users; unsigned int users;
/* report buffer (maximum 64 bytes) */
unsigned char buf[64];
/* Silabs internal registers (0..15) */ /* Silabs internal registers (0..15) */
unsigned short registers[RADIO_REGISTER_NUM]; unsigned short registers[RADIO_REGISTER_NUM];
/* RDS receive buffer */ /* RDS receive buffer */
struct work_struct work; struct delayed_work work;
wait_queue_head_t read_queue; wait_queue_head_t read_queue;
struct timer_list timer; struct mutex lock; /* buffer locking */
spinlock_t lock; /* buffer locking */
unsigned char *buffer; /* size is always multiple of three */ unsigned char *buffer; /* size is always multiple of three */
unsigned int buf_size; unsigned int buf_size;
unsigned int rd_index; unsigned int rd_index;
@ -434,28 +457,46 @@ struct si470x_device {
/* /*
* si470x_get_report - receive a HID report * si470x_get_report - receive a HID report
*/ */
static int si470x_get_report(struct si470x_device *radio, int size) static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
{ {
return usb_control_msg(radio->usbdev, unsigned char *report = (unsigned char *) buf;
int retval;
retval = usb_control_msg(radio->usbdev,
usb_rcvctrlpipe(radio->usbdev, 0), usb_rcvctrlpipe(radio->usbdev, 0),
HID_REQ_GET_REPORT, HID_REQ_GET_REPORT,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
radio->buf[0], 2, report[0], 2,
radio->buf, size, usb_timeout); buf, size, usb_timeout);
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": si470x_get_report: usb_control_msg returned %d\n",
retval);
return retval;
} }
/* /*
* si470x_set_report - send a HID report * si470x_set_report - send a HID report
*/ */
static int si470x_set_report(struct si470x_device *radio, int size) static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
{ {
return usb_control_msg(radio->usbdev, unsigned char *report = (unsigned char *) buf;
int retval;
retval = usb_control_msg(radio->usbdev,
usb_sndctrlpipe(radio->usbdev, 0), usb_sndctrlpipe(radio->usbdev, 0),
HID_REQ_SET_REPORT, HID_REQ_SET_REPORT,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
radio->buf[0], 2, report[0], 2,
radio->buf, size, usb_timeout); buf, size, usb_timeout);
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": si470x_set_report: usb_control_msg returned %d\n",
retval);
return retval;
} }
@ -464,13 +505,16 @@ static int si470x_set_report(struct si470x_device *radio, int size)
*/ */
static int si470x_get_register(struct si470x_device *radio, int regnr) static int si470x_get_register(struct si470x_device *radio, int regnr)
{ {
unsigned char buf[REGISTER_REPORT_SIZE];
int retval; int retval;
radio->buf[0] = REGISTER_REPORT(regnr); buf[0] = REGISTER_REPORT(regnr);
retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
retval = si470x_get_report(radio, REGISTER_REPORT_SIZE);
if (retval >= 0) if (retval >= 0)
radio->registers[regnr] = (radio->buf[1] << 8) | radio->buf[2]; radio->registers[regnr] = be16_to_cpu(get_unaligned(
(unsigned short *) &buf[1]));
return (retval < 0) ? -EINVAL : 0; return (retval < 0) ? -EINVAL : 0;
} }
@ -481,13 +525,14 @@ static int si470x_get_register(struct si470x_device *radio, int regnr)
*/ */
static int si470x_set_register(struct si470x_device *radio, int regnr) static int si470x_set_register(struct si470x_device *radio, int regnr)
{ {
unsigned char buf[REGISTER_REPORT_SIZE];
int retval; int retval;
radio->buf[0] = REGISTER_REPORT(regnr); buf[0] = REGISTER_REPORT(regnr);
radio->buf[1] = (radio->registers[regnr] & 0xff00) >> 8; put_unaligned(cpu_to_be16(radio->registers[regnr]),
radio->buf[2] = (radio->registers[regnr] & 0x00ff); (unsigned short *) &buf[1]);
retval = si470x_set_report(radio, REGISTER_REPORT_SIZE); retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
return (retval < 0) ? -EINVAL : 0; return (retval < 0) ? -EINVAL : 0;
} }
@ -498,18 +543,19 @@ static int si470x_set_register(struct si470x_device *radio, int regnr)
*/ */
static int si470x_get_all_registers(struct si470x_device *radio) static int si470x_get_all_registers(struct si470x_device *radio)
{ {
unsigned char buf[ENTIRE_REPORT_SIZE];
int retval; int retval;
int regnr; unsigned char regnr;
radio->buf[0] = ENTIRE_REPORT; buf[0] = ENTIRE_REPORT;
retval = si470x_get_report(radio, ENTIRE_REPORT_SIZE); retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
if (retval >= 0) if (retval >= 0)
for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
radio->registers[regnr] = radio->registers[regnr] = be16_to_cpu(get_unaligned(
(radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | (unsigned short *)
radio->buf[regnr * RADIO_REGISTER_SIZE + 2]; &buf[regnr * RADIO_REGISTER_SIZE + 1]));
return (retval < 0) ? -EINVAL : 0; return (retval < 0) ? -EINVAL : 0;
} }
@ -520,21 +566,28 @@ static int si470x_get_all_registers(struct si470x_device *radio)
*/ */
static int si470x_get_rds_registers(struct si470x_device *radio) static int si470x_get_rds_registers(struct si470x_device *radio)
{ {
unsigned char buf[RDS_REPORT_SIZE];
int retval; int retval;
int regnr;
int size; int size;
unsigned char regnr;
radio->buf[0] = RDS_REPORT; buf[0] = RDS_REPORT;
retval = usb_interrupt_msg(radio->usbdev, retval = usb_interrupt_msg(radio->usbdev,
usb_rcvctrlpipe(radio->usbdev, 1), usb_rcvintpipe(radio->usbdev, 1),
radio->buf, RDS_REPORT_SIZE, &size, usb_timeout); (void *) &buf, sizeof(buf), &size, usb_timeout);
if (size != sizeof(buf))
printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: "
"return size differs: %d != %zu\n", size, sizeof(buf));
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
"usb_interrupt_msg returned %d\n", retval);
if (retval >= 0) if (retval >= 0)
for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
radio->registers[STATUSRSSI + regnr] = radio->registers[STATUSRSSI + regnr] =
(radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | be16_to_cpu(get_unaligned((unsigned short *)
radio->buf[regnr * RADIO_REGISTER_SIZE + 2]; &buf[regnr * RADIO_REGISTER_SIZE + 1]));
return (retval < 0) ? -EINVAL : 0; return (retval < 0) ? -EINVAL : 0;
} }
@ -543,9 +596,11 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
/* /*
* si470x_set_chan - set the channel * si470x_set_chan - set the channel
*/ */
static int si470x_set_chan(struct si470x_device *radio, int chan) static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
{ {
int retval, i; int retval;
unsigned long timeout;
bool timed_out = 0;
/* start tuning */ /* start tuning */
radio->registers[CHANNEL] &= ~CHANNEL_CHAN; radio->registers[CHANNEL] &= ~CHANNEL_CHAN;
@ -555,16 +610,17 @@ static int si470x_set_chan(struct si470x_device *radio, int chan)
return retval; return retval;
/* wait till seek operation has completed */ /* wait till seek operation has completed */
i = 0; timeout = jiffies + msecs_to_jiffies(tune_timeout);
do { do {
retval = si470x_get_register(radio, STATUSRSSI); retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0) if (retval < 0)
return retval; return retval;
} while ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) && timed_out = time_after(jiffies, timeout);
(++i < seek_retries)); } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
if (i >= seek_retries) (!timed_out));
if (timed_out)
printk(KERN_WARNING DRIVER_NAME printk(KERN_WARNING DRIVER_NAME
": seek does not finish after %d tries\n", i); ": seek does not finish after %u ms\n", tune_timeout);
/* stop tuning */ /* stop tuning */
radio->registers[CHANNEL] &= ~CHANNEL_TUNE; radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
@ -575,9 +631,10 @@ static int si470x_set_chan(struct si470x_device *radio, int chan)
/* /*
* si470x_get_freq - get the frequency * si470x_get_freq - get the frequency
*/ */
static int si470x_get_freq(struct si470x_device *radio) static unsigned int si470x_get_freq(struct si470x_device *radio)
{ {
int spacing, band_bottom, chan, freq; unsigned int spacing, band_bottom, freq;
unsigned short chan;
int retval; int retval;
/* Spacing (kHz) */ /* Spacing (kHz) */
@ -616,9 +673,10 @@ static int si470x_get_freq(struct si470x_device *radio)
/* /*
* si470x_set_freq - set the frequency * si470x_set_freq - set the frequency
*/ */
static int si470x_set_freq(struct si470x_device *radio, int freq) static int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
{ {
int spacing, band_bottom, chan; unsigned int spacing, band_bottom;
unsigned short chan;
/* Spacing (kHz) */ /* Spacing (kHz) */
switch (space) { switch (space) {
@ -709,9 +767,17 @@ static int si470x_stop(struct si470x_device *radio)
*/ */
static int si470x_rds_on(struct si470x_device *radio) static int si470x_rds_on(struct si470x_device *radio)
{ {
int retval;
/* sysconfig 1 */ /* sysconfig 1 */
mutex_lock(&radio->lock);
radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS; radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
return si470x_set_register(radio, SYSCONFIG1); retval = si470x_set_register(radio, SYSCONFIG1);
if (retval < 0)
radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
mutex_unlock(&radio->lock);
return retval;
} }
@ -725,11 +791,10 @@ static int si470x_rds_on(struct si470x_device *radio)
*/ */
static void si470x_rds(struct si470x_device *radio) static void si470x_rds(struct si470x_device *radio)
{ {
unsigned char tmpbuf[3];
unsigned char blocknum; unsigned char blocknum;
unsigned char bler; /* rds block errors */ unsigned short bler; /* rds block errors */
unsigned short rds; unsigned short rds;
unsigned int i; unsigned char tmpbuf[3];
/* get rds blocks */ /* get rds blocks */
if (si470x_get_rds_registers(radio) < 0) if (si470x_get_rds_registers(radio) < 0)
@ -743,63 +808,58 @@ static void si470x_rds(struct si470x_device *radio)
return; return;
} }
/* copy four RDS blocks to internal buffer */ /* copy all four RDS blocks to internal buffer */
if (spin_trylock(&radio->lock)) { mutex_lock(&radio->lock);
/* process each rds block */ for (blocknum = 0; blocknum < 4; blocknum++) {
for (blocknum = 0; blocknum < 4; blocknum++) { switch (blocknum) {
switch (blocknum) { default:
default: bler = (radio->registers[STATUSRSSI] &
bler = (radio->registers[STATUSRSSI] & STATUSRSSI_BLERA) >> 9;
STATUSRSSI_BLERA) >> 9; rds = radio->registers[RDSA];
rds = radio->registers[RDSA]; break;
break; case 1:
case 1: bler = (radio->registers[READCHAN] &
bler = (radio->registers[READCHAN] & READCHAN_BLERB) >> 14;
READCHAN_BLERB) >> 14; rds = radio->registers[RDSB];
rds = radio->registers[RDSB]; break;
break; case 2:
case 2: bler = (radio->registers[READCHAN] &
bler = (radio->registers[READCHAN] & READCHAN_BLERC) >> 12;
READCHAN_BLERC) >> 12; rds = radio->registers[RDSC];
rds = radio->registers[RDSC]; break;
break; case 3:
case 3: bler = (radio->registers[READCHAN] &
bler = (radio->registers[READCHAN] & READCHAN_BLERD) >> 10;
READCHAN_BLERD) >> 10; rds = radio->registers[RDSD];
rds = radio->registers[RDSD]; break;
break; };
};
/* Fill the V4L2 RDS buffer */ /* Fill the V4L2 RDS buffer */
tmpbuf[0] = rds & 0x00ff; /* LSB */ put_unaligned(cpu_to_le16(rds), (unsigned short *) &tmpbuf);
tmpbuf[1] = (rds & 0xff00) >> 8;/* MSB */ tmpbuf[2] = blocknum; /* offset name */
tmpbuf[2] = blocknum; /* offset name */ tmpbuf[2] |= blocknum << 3; /* received offset */
tmpbuf[2] |= blocknum << 3; /* received offset */ if (bler > max_rds_errors)
if (bler > max_rds_errors) tmpbuf[2] |= 0x80; /* uncorrectable errors */
tmpbuf[2] |= 0x80; /* uncorrectable errors */ else if (bler > 0)
else if (bler > 0) tmpbuf[2] |= 0x40; /* corrected error(s) */
tmpbuf[2] |= 0x40; /* corrected error(s) */
/* copy RDS block to internal buffer */ /* copy RDS block to internal buffer */
for (i = 0; i < 3; i++) { memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
radio->buffer[radio->wr_index] = tmpbuf[i]; radio->wr_index += 3;
radio->wr_index++;
}
/* wrap write pointer */ /* wrap write pointer */
if (radio->wr_index >= radio->buf_size) if (radio->wr_index >= radio->buf_size)
radio->wr_index = 0; radio->wr_index = 0;
/* check for overflow */ /* check for overflow */
if (radio->wr_index == radio->rd_index) { if (radio->wr_index == radio->rd_index) {
/* increment and wrap read pointer */ /* increment and wrap read pointer */
radio->rd_index += 3; radio->rd_index += 3;
if (radio->rd_index >= radio->buf_size) if (radio->rd_index >= radio->buf_size)
radio->rd_index = 0; radio->rd_index = 0;
}
} }
spin_unlock(&radio->lock);
} }
mutex_unlock(&radio->lock);
/* wake up read queue */ /* wake up read queue */
if (radio->wr_index != radio->rd_index) if (radio->wr_index != radio->rd_index)
@ -807,30 +867,19 @@ static void si470x_rds(struct si470x_device *radio)
} }
/*
* si470x_timer - rds timer function
*/
static void si470x_timer(unsigned long data)
{
struct si470x_device *radio = (struct si470x_device *) data;
schedule_work(&radio->work);
}
/* /*
* si470x_work - rds work function * si470x_work - rds work function
*/ */
static void si470x_work(struct work_struct *work) static void si470x_work(struct work_struct *work)
{ {
struct si470x_device *radio = container_of(work, struct si470x_device, struct si470x_device *radio = container_of(work, struct si470x_device,
work); work.work);
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
return; return;
si470x_rds(radio); si470x_rds(radio);
mod_timer(&radio->timer, jiffies + msecs_to_jiffies(rds_poll_time)); schedule_delayed_work(&radio->work, msecs_to_jiffies(rds_poll_time));
} }
@ -852,44 +901,44 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
/* switch on rds reception */ /* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
si470x_rds_on(radio); si470x_rds_on(radio);
schedule_work(&radio->work); schedule_delayed_work(&radio->work,
msecs_to_jiffies(rds_poll_time));
} }
/* block if no new data available */ /* block if no new data available */
while (radio->wr_index == radio->rd_index) { while (radio->wr_index == radio->rd_index) {
if (file->f_flags & O_NONBLOCK) if (file->f_flags & O_NONBLOCK)
return -EWOULDBLOCK; return -EWOULDBLOCK;
interruptible_sleep_on(&radio->read_queue); if (wait_event_interruptible(radio->read_queue,
radio->wr_index != radio->rd_index) < 0)
return -EINTR;
} }
/* calculate block count from byte count */ /* calculate block count from byte count */
count /= 3; count /= 3;
/* copy RDS block out of internal buffer and to user buffer */ /* copy RDS block out of internal buffer and to user buffer */
if (spin_trylock(&radio->lock)) { mutex_lock(&radio->lock);
while (block_count < count) { while (block_count < count) {
if (radio->rd_index == radio->wr_index) if (radio->rd_index == radio->wr_index)
break; break;
/* always transfer rds complete blocks */ /* always transfer rds complete blocks */
if (copy_to_user(buf, if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
&radio->buffer[radio->rd_index], 3)) /* retval = -EFAULT; */
/* retval = -EFAULT; */ break;
break;
/* increment and wrap read pointer */ /* increment and wrap read pointer */
radio->rd_index += 3; radio->rd_index += 3;
if (radio->rd_index >= radio->buf_size) if (radio->rd_index >= radio->buf_size)
radio->rd_index = 0; radio->rd_index = 0;
/* increment counters */ /* increment counters */
block_count++; block_count++;
buf += 3; buf += 3;
retval += 3; retval += 3;
}
spin_unlock(&radio->lock);
} }
mutex_unlock(&radio->lock);
return retval; return retval;
} }
@ -906,7 +955,8 @@ static unsigned int si470x_fops_poll(struct file *file,
/* switch on rds reception */ /* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
si470x_rds_on(radio); si470x_rds_on(radio);
schedule_work(&radio->work); schedule_delayed_work(&radio->work,
msecs_to_jiffies(rds_poll_time));
} }
poll_wait(file, &radio->read_queue, pts); poll_wait(file, &radio->read_queue, pts);
@ -924,10 +974,22 @@ static unsigned int si470x_fops_poll(struct file *file,
static int si470x_fops_open(struct inode *inode, struct file *file) static int si470x_fops_open(struct inode *inode, struct file *file)
{ {
struct si470x_device *radio = video_get_drvdata(video_devdata(file)); struct si470x_device *radio = video_get_drvdata(video_devdata(file));
int retval;
radio->users++; radio->users++;
if (radio->users == 1)
return si470x_start(radio); retval = usb_autopm_get_interface(radio->intf);
if (retval < 0) {
radio->users--;
return -EIO;
}
if (radio->users == 1) {
retval = si470x_start(radio);
if (retval < 0)
usb_autopm_put_interface(radio->intf);
return retval;
}
return 0; return 0;
} }
@ -939,6 +1001,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
static int si470x_fops_release(struct inode *inode, struct file *file) static int si470x_fops_release(struct inode *inode, struct file *file)
{ {
struct si470x_device *radio = video_get_drvdata(video_devdata(file)); struct si470x_device *radio = video_get_drvdata(video_devdata(file));
int retval;
if (!radio) if (!radio)
return -ENODEV; return -ENODEV;
@ -946,13 +1009,14 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
radio->users--; radio->users--;
if (radio->users == 0) { if (radio->users == 0) {
/* stop rds reception */ /* stop rds reception */
del_timer_sync(&radio->timer); cancel_delayed_work_sync(&radio->work);
flush_scheduled_work();
/* cancel read processes */ /* cancel read processes */
wake_up_interruptible(&radio->read_queue); wake_up_interruptible(&radio->read_queue);
return si470x_stop(radio); retval = si470x_stop(radio);
usb_autopm_put_interface(radio->intf);
return retval;
} }
return 0; return 0;
@ -1030,7 +1094,7 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
sprintf(capability->bus_info, "USB"); sprintf(capability->bus_info, "USB");
capability->version = DRIVER_VERSION; capability->version = DRIVER_KERNEL_VERSION;
capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
return 0; return 0;
@ -1067,16 +1131,21 @@ static int si470x_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
static int si470x_vidioc_queryctrl(struct file *file, void *priv, static int si470x_vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc) struct v4l2_queryctrl *qc)
{ {
int i; unsigned char i;
int retval = -EINVAL;
for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) { for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) { if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) {
memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc)); memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
return 0; retval = 0;
break;
} }
} }
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": query control failed with %d\n", retval);
return -EINVAL; return retval;
} }
@ -1110,21 +1179,29 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
struct si470x_device *radio = video_get_drvdata(video_devdata(file)); struct si470x_device *radio = video_get_drvdata(video_devdata(file));
int retval;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_VOLUME:
radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
radio->registers[SYSCONFIG2] |= ctrl->value; radio->registers[SYSCONFIG2] |= ctrl->value;
return si470x_set_register(radio, SYSCONFIG2); retval = si470x_set_register(radio, SYSCONFIG2);
break;
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
if (ctrl->value == 1) if (ctrl->value == 1)
radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
else else
radio->registers[POWERCFG] |= POWERCFG_DMUTE; radio->registers[POWERCFG] |= POWERCFG_DMUTE;
return si470x_set_register(radio, POWERCFG); retval = si470x_set_register(radio, POWERCFG);
break;
default:
retval = -EINVAL;
} }
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": set control failed with %d\n", retval);
return -EINVAL; return retval;
} }
@ -1163,8 +1240,8 @@ static int si470x_vidioc_s_audio(struct file *file, void *priv,
static int si470x_vidioc_g_tuner(struct file *file, void *priv, static int si470x_vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner) struct v4l2_tuner *tuner)
{ {
int retval;
struct si470x_device *radio = video_get_drvdata(video_devdata(file)); struct si470x_device *radio = video_get_drvdata(video_devdata(file));
int retval;
if (tuner->index > 0) if (tuner->index > 0)
return -EINVAL; return -EINVAL;
@ -1220,6 +1297,7 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner) struct v4l2_tuner *tuner)
{ {
struct si470x_device *radio = video_get_drvdata(video_devdata(file)); struct si470x_device *radio = video_get_drvdata(video_devdata(file));
int retval;
if (tuner->index > 0) if (tuner->index > 0)
return -EINVAL; return -EINVAL;
@ -1229,7 +1307,12 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
else else
radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
return si470x_set_register(radio, POWERCFG); retval = si470x_set_register(radio, POWERCFG);
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": set tuner failed with %d\n", retval);
return retval;
} }
@ -1255,11 +1338,17 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq) struct v4l2_frequency *freq)
{ {
struct si470x_device *radio = video_get_drvdata(video_devdata(file)); struct si470x_device *radio = video_get_drvdata(video_devdata(file));
int retval;
if (freq->type != V4L2_TUNER_RADIO) if (freq->type != V4L2_TUNER_RADIO)
return -EINVAL; return -EINVAL;
return si470x_set_freq(radio, freq->frequency); retval = si470x_set_freq(radio, freq->frequency);
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": set frequency failed with %d\n", retval);
return 0;
} }
@ -1299,71 +1388,116 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct si470x_device *radio; struct si470x_device *radio;
int retval = -ENOMEM;
/* memory and interface allocations */ /* private data allocation */
radio = kmalloc(sizeof(struct si470x_device), GFP_KERNEL); radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
if (!radio) if (!radio)
return -ENOMEM; goto err_initial;
/* video device allocation */
radio->videodev = video_device_alloc(); radio->videodev = video_device_alloc();
if (!radio->videodev) { if (!radio->videodev)
kfree(radio); goto err_radio;
return -ENOMEM;
} /* initial configuration */
memcpy(radio->videodev, &si470x_viddev_template, memcpy(radio->videodev, &si470x_viddev_template,
sizeof(si470x_viddev_template)); sizeof(si470x_viddev_template));
radio->users = 0; radio->users = 0;
radio->usbdev = interface_to_usbdev(intf); radio->usbdev = interface_to_usbdev(intf);
radio->intf = intf;
mutex_init(&radio->lock);
video_set_drvdata(radio->videodev, radio); video_set_drvdata(radio->videodev, radio);
if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
printk(KERN_WARNING DRIVER_NAME
": Could not register video device\n");
video_device_release(radio->videodev);
kfree(radio);
return -EIO;
}
usb_set_intfdata(intf, radio);
/* show some infos about the specific device */ /* show some infos about the specific device */
if (si470x_get_all_registers(radio) < 0) { retval = -EIO;
video_device_release(radio->videodev); if (si470x_get_all_registers(radio) < 0)
kfree(radio); goto err_all;
return -EIO; printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
}
printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4x ChipID=0x%4.4x\n",
radio->registers[DEVICEID], radio->registers[CHIPID]); radio->registers[DEVICEID], radio->registers[CHIPID]);
/* check if firmware is current */ /* check if firmware is current */
if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) if ((radio->registers[CHIPID] & CHIPID_FIRMWARE)
< RADIO_SW_VERSION_CURRENT) < RADIO_SW_VERSION_CURRENT) {
printk(KERN_WARNING DRIVER_NAME printk(KERN_WARNING DRIVER_NAME
": This driver is known to work with chip version %d, " ": This driver is known to work with "
"but the device has firmware %d.\n" "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT);
DRIVER_NAME printk(KERN_WARNING DRIVER_NAME
"If you have some trouble using this driver, please " ": but the device has firmware version %hu.\n",
"report to V4L ML at video4linux-list@redhat.com\n", radio->registers[CHIPID] & CHIPID_FIRMWARE);
radio->registers[CHIPID] & CHIPID_FIRMWARE, printk(KERN_WARNING DRIVER_NAME
RADIO_SW_VERSION_CURRENT); ": If you have some trouble using this driver,\n");
printk(KERN_WARNING DRIVER_NAME
": please report to V4L ML at "
"video4linux-list@redhat.com\n");
}
/* set initial frequency */ /* set initial frequency */
si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
/* rds initialization */ /* rds buffer allocation */
radio->buf_size = rds_buf * 3; radio->buf_size = rds_buf * 3;
radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
if (!radio->buffer) { if (!radio->buffer)
video_device_release(radio->videodev); goto err_all;
kfree(radio);
return -ENOMEM; /* rds buffer configuration */
}
radio->wr_index = 0; radio->wr_index = 0;
radio->rd_index = 0; radio->rd_index = 0;
init_waitqueue_head(&radio->read_queue); init_waitqueue_head(&radio->read_queue);
/* prepare polling via eventd */ /* prepare rds work function */
INIT_WORK(&radio->work, si470x_work); INIT_DELAYED_WORK(&radio->work, si470x_work);
init_timer(&radio->timer);
radio->timer.function = si470x_timer; /* register video device */
radio->timer.data = (unsigned long) radio; if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
printk(KERN_WARNING DRIVER_NAME
": Could not register video device\n");
goto err_all;
}
usb_set_intfdata(intf, radio);
return 0;
err_all:
video_device_release(radio->videodev);
kfree(radio->buffer);
err_radio:
kfree(radio);
err_initial:
return retval;
}
/*
* si470x_usb_driver_suspend - suspend the device
*/
static int si470x_usb_driver_suspend(struct usb_interface *intf,
pm_message_t message)
{
struct si470x_device *radio = usb_get_intfdata(intf);
printk(KERN_INFO DRIVER_NAME ": suspending now...\n");
cancel_delayed_work_sync(&radio->work);
return 0;
}
/*
* si470x_usb_driver_resume - resume the device
*/
static int si470x_usb_driver_resume(struct usb_interface *intf)
{
struct si470x_device *radio = usb_get_intfdata(intf);
printk(KERN_INFO DRIVER_NAME ": resuming now...\n");
mutex_lock(&radio->lock);
if (radio->users && radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS)
schedule_delayed_work(&radio->work,
msecs_to_jiffies(rds_poll_time));
mutex_unlock(&radio->lock);
return 0; return 0;
} }
@ -1376,15 +1510,11 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
{ {
struct si470x_device *radio = usb_get_intfdata(intf); struct si470x_device *radio = usb_get_intfdata(intf);
del_timer_sync(&radio->timer); cancel_delayed_work_sync(&radio->work);
flush_scheduled_work();
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
if (radio) { video_unregister_device(radio->videodev);
video_unregister_device(radio->videodev); kfree(radio->buffer);
kfree(radio->buffer); kfree(radio);
kfree(radio);
}
} }
@ -1392,10 +1522,13 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
* si470x_usb_driver - usb driver interface * si470x_usb_driver - usb driver interface
*/ */
static struct usb_driver si470x_usb_driver = { static struct usb_driver si470x_usb_driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.probe = si470x_usb_driver_probe, .probe = si470x_usb_driver_probe,
.disconnect = si470x_usb_driver_disconnect, .disconnect = si470x_usb_driver_disconnect,
.id_table = si470x_usb_driver_id_table, .suspend = si470x_usb_driver_suspend,
.resume = si470x_usb_driver_resume,
.id_table = si470x_usb_driver_id_table,
.supports_autosuspend = 1,
}; };
@ -1409,7 +1542,7 @@ static struct usb_driver si470x_usb_driver = {
*/ */
static int __init si470x_module_init(void) static int __init si470x_module_init(void)
{ {
printk(KERN_INFO DRIVER_DESC "\n"); printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n");
return usb_register(&si470x_usb_driver); return usb_register(&si470x_usb_driver);
} }
@ -1429,4 +1562,4 @@ module_exit(si470x_module_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION("1.0.4"); MODULE_VERSION(DRIVER_VERSION);

View File

@ -4,14 +4,14 @@
menuconfig VIDEO_CAPTURE_DRIVERS menuconfig VIDEO_CAPTURE_DRIVERS
bool "Video capture adapters" bool "Video capture adapters"
depends on VIDEO_DEV depends on VIDEO_V4L2
default y default y
---help--- ---help---
Say Y here to enable selecting the video adapters for Say Y here to enable selecting the video adapters for
webcams, analog TV, and hybrid analog/digital TV. webcams, analog TV, and hybrid analog/digital TV.
Some of those devices also supports FM radio. Some of those devices also supports FM radio.
if VIDEO_CAPTURE_DRIVERS && VIDEO_DEV if VIDEO_CAPTURE_DRIVERS && VIDEO_V4L2
config VIDEO_ADV_DEBUG config VIDEO_ADV_DEBUG
bool "Enable advanced debug functionality" bool "Enable advanced debug functionality"

View File

@ -10,8 +10,9 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o
stkwebcam-objs := stk-webcam.o stk-sensor.o stkwebcam-objs := stk-webcam.o stk-sensor.o
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \ obj-$(CONFIG_VIDEO_DEV) += videodev.o compat_ioctl32.o v4l2-int-device.o
v4l2-int-device.o
obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o

View File

@ -2354,8 +2354,8 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
BUG(); BUG();
} }
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.vb_lock);
kfree(fh->ov.clips); kfree(fh->ov.clips);
fh->ov.clips = clips; fh->ov.clips = clips;
fh->ov.nclips = n; fh->ov.nclips = n;
@ -2376,7 +2376,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
retval = bttv_switch_overlay(btv,fh,new); retval = bttv_switch_overlay(btv,fh,new);
} }
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
return retval; return retval;
} }
@ -2576,7 +2576,7 @@ static int bttv_s_fmt_cap(struct file *file, void *priv,
fmt = format_by_fourcc(f->fmt.pix.pixelformat); fmt = format_by_fourcc(f->fmt.pix.pixelformat);
/* update our state informations */ /* update our state informations */
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.vb_lock);
fh->fmt = fmt; fh->fmt = fmt;
fh->cap.field = f->fmt.pix.field; fh->cap.field = f->fmt.pix.field;
fh->cap.last = V4L2_FIELD_NONE; fh->cap.last = V4L2_FIELD_NONE;
@ -2585,7 +2585,7 @@ static int bttv_s_fmt_cap(struct file *file, void *priv,
btv->init.fmt = fmt; btv->init.fmt = fmt;
btv->init.width = f->fmt.pix.width; btv->init.width = f->fmt.pix.width;
btv->init.height = f->fmt.pix.height; btv->init.height = f->fmt.pix.height;
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
return 0; return 0;
} }
@ -2611,11 +2611,11 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
unsigned int i; unsigned int i;
struct bttv_fh *fh = priv; struct bttv_fh *fh = priv;
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.vb_lock);
retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
V4L2_MEMORY_MMAP); V4L2_MEMORY_MMAP);
if (retval < 0) { if (retval < 0) {
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
return retval; return retval;
} }
@ -2627,7 +2627,7 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
for (i = 0; i < gbuffers; i++) for (i = 0; i < gbuffers; i++)
mbuf->offsets[i] = i * gbufsize; mbuf->offsets[i] = i * gbufsize;
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
return 0; return 0;
} }
#endif #endif
@ -2756,10 +2756,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
if (!check_alloc_btres(btv, fh, RESOURCE_OVERLAY)) if (!check_alloc_btres(btv, fh, RESOURCE_OVERLAY))
return -EBUSY; return -EBUSY;
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.vb_lock);
if (on) { if (on) {
fh->ov.tvnorm = btv->tvnorm; fh->ov.tvnorm = btv->tvnorm;
new = videobuf_pci_alloc(sizeof(*new)); new = videobuf_pci_alloc(sizeof(*new));
new->crop = btv->crop[!!fh->do_crop].rect;
bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
} else { } else {
new = NULL; new = NULL;
@ -2767,7 +2768,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
/* switch over */ /* switch over */
retval = bttv_switch_overlay(btv, fh, new); retval = bttv_switch_overlay(btv, fh, new);
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
return retval; return retval;
} }
@ -2806,7 +2807,7 @@ static int bttv_s_fbuf(struct file *file, void *f,
} }
/* ok, accept it */ /* ok, accept it */
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.vb_lock);
btv->fbuf.base = fb->base; btv->fbuf.base = fb->base;
btv->fbuf.fmt.width = fb->fmt.width; btv->fbuf.fmt.width = fb->fmt.width;
btv->fbuf.fmt.height = fb->fmt.height; btv->fbuf.fmt.height = fb->fmt.height;
@ -2838,7 +2839,7 @@ static int bttv_s_fbuf(struct file *file, void *f,
retval = bttv_switch_overlay(btv, fh, new); retval = bttv_switch_overlay(btv, fh, new);
} }
} }
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
return retval; return retval;
} }
@ -3090,7 +3091,7 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
fh->do_crop = 1; fh->do_crop = 1;
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.vb_lock);
if (fh->width < c.min_scaled_width) { if (fh->width < c.min_scaled_width) {
fh->width = c.min_scaled_width; fh->width = c.min_scaled_width;
@ -3108,7 +3109,7 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
btv->init.height = c.max_scaled_height; btv->init.height = c.max_scaled_height;
} }
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
return 0; return 0;
} }
@ -3177,30 +3178,25 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
} else { } else {
/* read() capture */ /* read() capture */
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.vb_lock);
if (NULL == fh->cap.read_buf) { if (NULL == fh->cap.read_buf) {
/* need to capture a new frame */ /* need to capture a new frame */
if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) { if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
mutex_unlock(&fh->cap.lock); goto err;
return POLLERR;
}
fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize); fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize);
if (NULL == fh->cap.read_buf) { if (NULL == fh->cap.read_buf)
mutex_unlock(&fh->cap.lock); goto err;
return POLLERR;
}
fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
field = videobuf_next_field(&fh->cap); field = videobuf_next_field(&fh->cap);
if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) { if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
kfree (fh->cap.read_buf); kfree (fh->cap.read_buf);
fh->cap.read_buf = NULL; fh->cap.read_buf = NULL;
mutex_unlock(&fh->cap.lock); goto err;
return POLLERR;
} }
fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
fh->cap.read_off = 0; fh->cap.read_off = 0;
} }
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
buf = (struct bttv_buffer*)fh->cap.read_buf; buf = (struct bttv_buffer*)fh->cap.read_buf;
} }
@ -3209,6 +3205,9 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
buf->vb.state == VIDEOBUF_ERROR) buf->vb.state == VIDEOBUF_ERROR)
return POLLIN|POLLRDNORM; return POLLIN|POLLRDNORM;
return 0; return 0;
err:
mutex_unlock(&fh->cap.vb_lock);
return POLLERR;
} }
static int bttv_open(struct inode *inode, struct file *file) static int bttv_open(struct inode *inode, struct file *file)

View File

@ -352,13 +352,13 @@ int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
because vbi_fmt.end counts field lines times two. */ because vbi_fmt.end counts field lines times two. */
end = max(frt->fmt.vbi.start[0], start1) * 2 + 2; end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
mutex_lock(&fh->vbi.lock); mutex_lock(&fh->vbi.vb_lock);
fh->vbi_fmt.fmt = frt->fmt.vbi; fh->vbi_fmt.fmt = frt->fmt.vbi;
fh->vbi_fmt.tvnorm = tvnorm; fh->vbi_fmt.tvnorm = tvnorm;
fh->vbi_fmt.end = end; fh->vbi_fmt.end = end;
mutex_unlock(&fh->vbi.lock); mutex_unlock(&fh->vbi.vb_lock);
rc = 0; rc = 0;

View File

@ -609,13 +609,19 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
struct cx88_core *core = drv->core; struct cx88_core *core = drv->core;
/* Fail a request for hardware if the device is busy. */ /* Fail a request for hardware if the device is busy. */
if (core->active_type_id != CX88_BOARD_NONE) if (core->active_type_id != CX88_BOARD_NONE &&
core->active_type_id != drv->type_id)
return -EBUSY; return -EBUSY;
if (drv->advise_acquire) if (drv->advise_acquire)
{ {
core->active_type_id = drv->type_id; mutex_lock(&drv->core->lock);
drv->advise_acquire(drv); core->active_ref++;
if (core->active_type_id == CX88_BOARD_NONE) {
core->active_type_id = drv->type_id;
drv->advise_acquire(drv);
}
mutex_unlock(&drv->core->lock);
mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
} }
@ -628,12 +634,14 @@ static int cx8802_request_release(struct cx8802_driver *drv)
{ {
struct cx88_core *core = drv->core; struct cx88_core *core = drv->core;
if (drv->advise_release) mutex_lock(&drv->core->lock);
if (drv->advise_release && --core->active_ref == 0)
{ {
drv->advise_release(drv); drv->advise_release(drv);
core->active_type_id = CX88_BOARD_NONE; core->active_type_id = CX88_BOARD_NONE;
mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
} }
mutex_unlock(&drv->core->lock);
return 0; return 0;
} }

View File

@ -336,6 +336,7 @@ struct cx88_core {
/* cx88-video needs to access cx8802 for hybrid tuner pll access. */ /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
struct cx8802_dev *dvbdev; struct cx8802_dev *dvbdev;
enum cx88_board_type active_type_id; enum cx88_board_type active_type_id;
int active_ref;
}; };
struct cx8800_dev; struct cx8800_dev;

View File

@ -35,7 +35,6 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/module.h> #include <linux/module.h>
#include <sound/driver.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
@ -270,8 +269,11 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
dprintk("opening device and trying to acquire exclusive lock\n"); dprintk("opening device and trying to acquire exclusive lock\n");
/* Sets volume, mute, etc */ /* Sets volume, mute, etc */
dev->mute = 0; dev->mute = 0;
mutex_lock(&dev->lock);
ret = em28xx_audio_analog_set(dev); ret = em28xx_audio_analog_set(dev);
mutex_unlock(&dev->lock);
if (ret < 0) if (ret < 0)
goto err; goto err;
@ -303,7 +305,9 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
dprintk("closing device\n"); dprintk("closing device\n");
dev->mute = 1; dev->mute = 1;
mutex_lock(&dev->lock);
em28xx_audio_analog_set(dev); em28xx_audio_analog_set(dev);
mutex_unlock(&dev->lock);
if (dev->adev->users == 0 && dev->adev->shutdown == 1) { if (dev->adev->users == 0 && dev->adev->shutdown == 1) {
dprintk("audio users: %d\n", dev->adev->users); dprintk("audio users: %d\n", dev->adev->users);

View File

@ -393,15 +393,15 @@ struct em28xx_board em28xx_boards[] = {
.input = { { .input = { {
.type = EM28XX_VMUX_TELEVISION, .type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2, .vmux = SAA7115_COMPOSITE2,
.amux = 1, .amux = EM28XX_AMUX_LINE_IN,
}, { }, {
.type = EM28XX_VMUX_COMPOSITE1, .type = EM28XX_VMUX_COMPOSITE1,
.vmux = SAA7115_COMPOSITE0, .vmux = SAA7115_COMPOSITE0,
.amux = 1, .amux = EM28XX_AMUX_LINE_IN,
}, { }, {
.type = EM28XX_VMUX_SVIDEO, .type = EM28XX_VMUX_SVIDEO,
.vmux = SAA7115_SVIDEO3, .vmux = SAA7115_SVIDEO3,
.amux = 1, .amux = EM28XX_AMUX_LINE_IN,
} }, } },
}, },
}; };
@ -441,6 +441,8 @@ struct usb_device_id em28xx_id_table [] = {
.driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
{ USB_DEVICE(0x2040, 0x6500), { USB_DEVICE(0x2040, 0x6500),
.driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
{ USB_DEVICE(0x2040, 0x6502),
.driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
{ USB_DEVICE(0x2040, 0x6513), { USB_DEVICE(0x2040, 0x6513),
.driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
{ USB_DEVICE(0x0ccd, 0x0042), { USB_DEVICE(0x0ccd, 0x0042),

View File

@ -72,7 +72,8 @@ u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */ const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */
void *buff = NULL; void *buff = NULL;
u32 i; u32 i;
em28xx_coredbg("requested %i buffers with size %zi", count, imagesize); em28xx_coredbg("requested %i buffers with size %zi\n",
count, imagesize);
if (count > EM28XX_NUM_FRAMES) if (count > EM28XX_NUM_FRAMES)
count = EM28XX_NUM_FRAMES; count = EM28XX_NUM_FRAMES;
@ -150,7 +151,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
if (reg_debug){ if (reg_debug){
printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); printk(ret < 0 ? " failed!\n" : "%02x values: ", ret);
for (byte = 0; byte < len; byte++) { for (byte = 0; byte < len; byte++) {
printk(" %02x", buf[byte]); printk(" %02x", (unsigned char)buf[byte]);
} }
printk("\n"); printk("\n");
} }
@ -177,7 +178,8 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
0x0000, reg, &val, 1, HZ); 0x0000, reg, &val, 1, HZ);
if (reg_debug) if (reg_debug)
printk(ret < 0 ? " failed!\n" : "%02x\n", val); printk(ret < 0 ? " failed!\n" :
"%02x\n", (unsigned char) val);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -237,7 +239,7 @@ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
* sets only some bits (specified by bitmask) of a register, by first reading * sets only some bits (specified by bitmask) of a register, by first reading
* the actual value * the actual value
*/ */
int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
u8 bitmask) u8 bitmask)
{ {
int oldval; int oldval;
@ -254,26 +256,31 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
*/ */
static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
{ {
int ret; int ret, i;
u8 addr = reg & 0x7f; u8 addr = reg & 0x7f;
if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0) if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0)
return ret; return ret;
if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0)
return ret; return ret;
if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
return ret; /* Wait up to 50 ms for AC97 command to complete */
else if (((u8) ret) & 0x01) { for (i = 0; i < 10; i++) {
em28xx_warn ("AC97 command still being executed: not handled properly!\n"); if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
return ret;
if (!((u8) ret) & 0x01)
return 0;
msleep(5);
} }
em28xx_warn ("AC97 command still being executed: not handled properly!\n");
return 0; return 0;
} }
int em28xx_set_audio_source(struct em28xx *dev) static int em28xx_set_audio_source(struct em28xx *dev)
{ {
static char *enable = "\x08\x08"; static char *enable = "\x08\x08";
static char *disable = "\x08\x88"; static char *disable = "\x08\x88";
char *video = enable, *line = disable; char *video = enable, *line = disable;
int ret, no_ac97; int ret;
u8 input; u8 input;
if (dev->is_em2800) { if (dev->is_em2800) {
@ -293,11 +300,9 @@ int em28xx_set_audio_source(struct em28xx *dev)
switch (dev->ctl_ainput) { switch (dev->ctl_ainput) {
case EM28XX_AMUX_VIDEO: case EM28XX_AMUX_VIDEO:
input = EM28XX_AUDIO_SRC_TUNER; input = EM28XX_AUDIO_SRC_TUNER;
no_ac97 = 1;
break; break;
case EM28XX_AMUX_LINE_IN: case EM28XX_AMUX_LINE_IN:
input = EM28XX_AUDIO_SRC_LINE; input = EM28XX_AUDIO_SRC_LINE;
no_ac97 = 1;
break; break;
case EM28XX_AMUX_AC97_VIDEO: case EM28XX_AMUX_AC97_VIDEO:
input = EM28XX_AUDIO_SRC_LINE; input = EM28XX_AUDIO_SRC_LINE;
@ -313,12 +318,11 @@ int em28xx_set_audio_source(struct em28xx *dev)
ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
if (ret < 0) if (ret < 0)
return ret; return ret;
msleep(5);
if (no_ac97) /* Sets AC97 mixer registers
return 0; This is seems to be needed, even for non-ac97 configs
*/
/* Sets AC97 mixer registers */
ret = em28xx_write_ac97(dev, VIDEO_AC97, video); ret = em28xx_write_ac97(dev, VIDEO_AC97, video);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -337,9 +341,10 @@ int em28xx_audio_analog_set(struct em28xx *dev)
s[0] |= 0x1f - dev->volume; s[0] |= 0x1f - dev->volume;
s[1] |= 0x1f - dev->volume; s[1] |= 0x1f - dev->volume;
if (dev->mute) /* Mute */
s[1] |= 0x80; s[1] |= 0x80;
ret = em28xx_write_ac97(dev, MASTER_AC97, s); ret = em28xx_write_ac97(dev, MASTER_AC97, s);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -357,6 +362,11 @@ int em28xx_audio_analog_set(struct em28xx *dev)
/* Selects the proper audio input */ /* Selects the proper audio input */
ret = em28xx_set_audio_source(dev); ret = em28xx_set_audio_source(dev);
/* Unmute device */
if (!dev->mute)
s[1] &= ~0x80;
ret = em28xx_write_ac97(dev, MASTER_AC97, s);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
@ -667,7 +677,7 @@ static void em28xx_isocIrq(struct urb *urb)
continue; continue;
} }
if (urb->iso_frame_desc[i].actual_length > if (urb->iso_frame_desc[i].actual_length >
dev->max_pkt_size) { urb->iso_frame_desc[i].length) {
em28xx_isocdbg("packet bigger than packet size"); em28xx_isocdbg("packet bigger than packet size");
continue; continue;
} }
@ -713,8 +723,11 @@ void em28xx_uninit_isoc(struct em28xx *dev)
for (i = 0; i < EM28XX_NUM_BUFS; i++) { for (i = 0; i < EM28XX_NUM_BUFS; i++) {
if (dev->urb[i]) { if (dev->urb[i]) {
usb_kill_urb(dev->urb[i]); usb_kill_urb(dev->urb[i]);
if (dev->transfer_buffer[i]){ if (dev->transfer_buffer[i]) {
usb_buffer_free(dev->udev,(EM28XX_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma); usb_buffer_free(dev->udev,
dev->urb[i]->transfer_buffer_length,
dev->transfer_buffer[i],
dev->urb[i]->transfer_dma);
} }
usb_free_urb(dev->urb[i]); usb_free_urb(dev->urb[i]);
} }
@ -732,7 +745,10 @@ int em28xx_init_isoc(struct em28xx *dev)
{ {
/* change interface to 3 which allows the biggest packet sizes */ /* change interface to 3 which allows the biggest packet sizes */
int i, errCode; int i, errCode;
const int sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size; int sb_size;
em28xx_set_alternate(dev);
sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
/* reset streaming vars */ /* reset streaming vars */
dev->frame_current = NULL; dev->frame_current = NULL;
@ -741,7 +757,7 @@ int em28xx_init_isoc(struct em28xx *dev)
/* allocate urbs */ /* allocate urbs */
for (i = 0; i < EM28XX_NUM_BUFS; i++) { for (i = 0; i < EM28XX_NUM_BUFS; i++) {
struct urb *urb; struct urb *urb;
int j, k; int j;
/* allocate transfer buffer */ /* allocate transfer buffer */
urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL); urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
if (!urb){ if (!urb){
@ -749,7 +765,9 @@ int em28xx_init_isoc(struct em28xx *dev)
em28xx_uninit_isoc(dev); em28xx_uninit_isoc(dev);
return -ENOMEM; return -ENOMEM;
} }
dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,&urb->transfer_dma); dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size,
GFP_KERNEL,
&urb->transfer_dma);
if (!dev->transfer_buffer[i]) { if (!dev->transfer_buffer[i]) {
em28xx_errdev em28xx_errdev
("unable to allocate %i bytes for transfer buffer %i\n", ("unable to allocate %i bytes for transfer buffer %i\n",
@ -762,22 +780,22 @@ int em28xx_init_isoc(struct em28xx *dev)
urb->dev = dev->udev; urb->dev = dev->udev;
urb->context = dev; urb->context = dev;
urb->pipe = usb_rcvisocpipe(dev->udev, 0x82); urb->pipe = usb_rcvisocpipe(dev->udev, 0x82);
urb->transfer_flags = URB_ISO_ASAP; urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
urb->interval = 1; urb->interval = 1;
urb->transfer_buffer = dev->transfer_buffer[i]; urb->transfer_buffer = dev->transfer_buffer[i];
urb->complete = em28xx_isocIrq; urb->complete = em28xx_isocIrq;
urb->number_of_packets = EM28XX_NUM_PACKETS; urb->number_of_packets = EM28XX_NUM_PACKETS;
urb->transfer_buffer_length = sb_size; urb->transfer_buffer_length = sb_size;
for (j = k = 0; j < EM28XX_NUM_PACKETS; for (j = 0; j < EM28XX_NUM_PACKETS; j++) {
j++, k += dev->max_pkt_size) { urb->iso_frame_desc[j].offset = j * dev->max_pkt_size;
urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].length = dev->max_pkt_size;
urb->iso_frame_desc[j].length =
dev->max_pkt_size;
} }
dev->urb[i] = urb; dev->urb[i] = urb;
} }
/* submit urbs */ /* submit urbs */
em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n",
EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size);
for (i = 0; i < EM28XX_NUM_BUFS; i++) { for (i = 0; i < EM28XX_NUM_BUFS; i++) {
errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL); errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);
if (errCode) { if (errCode) {
@ -794,22 +812,31 @@ int em28xx_init_isoc(struct em28xx *dev)
int em28xx_set_alternate(struct em28xx *dev) int em28xx_set_alternate(struct em28xx *dev)
{ {
int errCode, prev_alt = dev->alt; int errCode, prev_alt = dev->alt;
dev->alt = alt; int i;
if (dev->alt == 0) { unsigned int min_pkt_size = dev->bytesperline+4;
int i;
for(i=0;i< dev->num_alt; i++) /* When image size is bigger than a ceirtain value,
if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) the frame size should be increased, otherwise, only
dev->alt=i; green screen will be received.
} */
if (dev->frame_size > 720*240*2)
min_pkt_size *= 2;
for (i = 0; i < dev->num_alt; i++)
if (dev->alt_max_pkt_size[i] >= min_pkt_size)
break;
dev->alt = i;
if (dev->alt != prev_alt) { if (dev->alt != prev_alt) {
em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
min_pkt_size, dev->alt);
dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", dev->alt, em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
dev->max_pkt_size); dev->alt, dev->max_pkt_size);
errCode = usb_set_interface(dev->udev, 0, dev->alt); errCode = usb_set_interface(dev->udev, 0, dev->alt);
if (errCode < 0) { if (errCode < 0) {
em28xx_errdev ("cannot change alternate number to %d (error=%i)\n", em28xx_errdev ("cannot change alternate number to %d (error=%i)\n",
dev->alt, errCode); dev->alt, errCode);
return errCode; return errCode;
} }
} }

View File

@ -189,7 +189,7 @@ static void video_mux(struct em28xx *dev, int index)
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
} }
em28xx_set_audio_source(dev); em28xx_audio_analog_set(dev);
} }
/* Usage lock check functions */ /* Usage lock check functions */
@ -830,6 +830,63 @@ static int vidioc_s_frequency(struct file *file, void *priv,
return 0; return 0;
} }
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int em28xx_reg_len(int reg)
{
switch (reg) {
case AC97LSB_REG:
case HSCALELOW_REG:
case VSCALELOW_REG:
return 2;
default:
return 1;
}
}
static int vidioc_g_register(struct file *file, void *priv,
struct v4l2_register *reg)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
int ret;
if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
return -EINVAL;
if (em28xx_reg_len(reg->reg) == 1) {
ret = em28xx_read_reg(dev, reg->reg);
if (ret < 0)
return ret;
reg->val = ret;
} else {
u64 val = 0;
ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
reg->reg, (char *)&val, 2);
if (ret < 0)
return ret;
reg->val = cpu_to_le64((__u64)val);
}
return 0;
}
static int vidioc_s_register(struct file *file, void *priv,
struct v4l2_register *reg)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
u64 buf;
buf = le64_to_cpu((__u64)reg->val);
return em28xx_write_regs(dev, reg->reg, (char *)&buf,
em28xx_reg_len(reg->reg));
}
#endif
static int vidioc_cropcap(struct file *file, void *priv, static int vidioc_cropcap(struct file *file, void *priv,
struct v4l2_cropcap *cc) struct v4l2_cropcap *cc)
{ {
@ -1295,8 +1352,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
filp->private_data = fh; filp->private_data = fh;
if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
em28xx_set_alternate(dev);
dev->width = norm_maxw(dev); dev->width = norm_maxw(dev);
dev->height = norm_maxh(dev); dev->height = norm_maxh(dev);
dev->frame_size = dev->width * dev->height * 2; dev->frame_size = dev->width * dev->height * 2;
@ -1305,6 +1360,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
dev->hscale = 0; dev->hscale = 0;
dev->vscale = 0; dev->vscale = 0;
em28xx_set_alternate(dev);
em28xx_capture_start(dev, 1); em28xx_capture_start(dev, 1);
em28xx_resolution_set(dev); em28xx_resolution_set(dev);
@ -1730,6 +1786,10 @@ static const struct video_device em28xx_video_template = {
.vidioc_s_tuner = vidioc_s_tuner, .vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency, .vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency, .vidioc_s_frequency = vidioc_s_frequency,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.vidioc_g_register = vidioc_g_register,
.vidioc_s_register = vidioc_s_register,
#endif
.tvnorms = V4L2_STD_ALL, .tvnorms = V4L2_STD_ALL,
.current_norm = V4L2_STD_PAL, .current_norm = V4L2_STD_PAL,
@ -1752,6 +1812,10 @@ static struct video_device em28xx_radio_template = {
.vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_g_frequency = vidioc_g_frequency, .vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency, .vidioc_s_frequency = vidioc_s_frequency,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.vidioc_g_register = vidioc_g_register,
.vidioc_s_register = vidioc_s_register,
#endif
}; };
/******************************** usb interface *****************************************/ /******************************** usb interface *****************************************/
@ -1796,10 +1860,10 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
} }
EXPORT_SYMBOL(em28xx_unregister_extension); EXPORT_SYMBOL(em28xx_unregister_extension);
struct video_device *em28xx_vdev_init(struct em28xx *dev, static struct video_device *em28xx_vdev_init(struct em28xx *dev,
const struct video_device *template, const struct video_device *template,
const int type, const int type,
const char *type_name) const char *type_name)
{ {
struct video_device *vfd; struct video_device *vfd;
@ -2064,6 +2128,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
snprintf(dev->name, 29, "em28xx #%d", nr); snprintf(dev->name, 29, "em28xx #%d", nr);
dev->devno = nr; dev->devno = nr;
dev->model = id->driver_info; dev->model = id->driver_info;
dev->alt = -1;
/* Checks if audio is provided by some interface */ /* Checks if audio is provided by some interface */
for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {

View File

@ -33,7 +33,7 @@
#define UNSET -1 #define UNSET -1
/* maximum number of em28xx boards */ /* maximum number of em28xx boards */
#define EM28XX_MAXBOARDS 1 /*FIXME: should be bigger */ #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
/* maximum number of frames that can be queued */ /* maximum number of frames that can be queued */
#define EM28XX_NUM_FRAMES 5 #define EM28XX_NUM_FRAMES 5
@ -345,9 +345,6 @@ int em28xx_read_reg(struct em28xx *dev, u16 reg);
int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
int len); int len);
int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
u8 bitmask);
int em28xx_set_audio_source(struct em28xx *dev);
int em28xx_audio_analog_set(struct em28xx *dev); int em28xx_audio_analog_set(struct em28xx *dev);
int em28xx_colorlevels_set_default(struct em28xx *dev); int em28xx_colorlevels_set_default(struct em28xx *dev);

View File

@ -928,27 +928,38 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET, .tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT, .tda9887_conf = TDA9887_PRESENT,
.gpiomask = 0x03,
.inputs = {{ .inputs = {{
.name = name_tv, .name = name_tv,
.vmux = 1, .vmux = 1,
.amux = TV, .amux = TV,
.tv = 1, .tv = 1,
},{ .gpio = 0x00,
}, {
.name = name_comp1, .name = name_comp1,
.vmux = 0,
.amux = LINE2,
},{
.name = name_comp2,
.vmux = 3, .vmux = 3,
.amux = LINE2, .amux = LINE1,
},{ .gpio = 0x02,
}, {
.name = name_comp2,
.vmux = 0,
.amux = LINE1,
.gpio = 0x02,
}, {
.name = name_svideo, .name = name_svideo,
.vmux = 8, .vmux = 8,
.amux = LINE2, .amux = LINE1,
}}, .gpio = 0x02,
} },
.radio = { .radio = {
.name = name_radio, .name = name_radio,
.amux = LINE2, .amux = LINE1,
.gpio = 0x01,
},
.mute = {
.name = name_mute,
.amux = TV,
.gpio = 0x00,
}, },
}, },
[SAA7134_BOARD_BMK_MPEX_TUNER] = { [SAA7134_BOARD_BMK_MPEX_TUNER] = {
@ -3912,6 +3923,74 @@ struct saa7134_board saa7134_boards[] = {
}, },
.mpeg = SAA7134_MPEG_EMPRESS, .mpeg = SAA7134_MPEG_EMPRESS,
}, },
[SAA7134_BOARD_TWINHAN_DTV_DVB_3056] = {
.name = "Twinhan Hybrid DTV-DVB 3056 PCI",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_TDA8290,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tuner_config = 2,
.mpeg = SAA7134_MPEG_DVB,
.gpiomask = 0x0200000,
.inputs = {{
.name = name_tv,
.vmux = 1,
.amux = TV,
.tv = 1,
}, {
.name = name_comp1,
.vmux = 3,
.amux = LINE1,
}, {
.name = name_svideo,
.vmux = 8, /* untested */
.amux = LINE1,
} },
.radio = {
.name = name_radio,
.amux = TV,
.gpio = 0x0200000,
},
},
[SAA7134_BOARD_GENIUS_TVGO_A11MCE] = {
/* Adrian Pardini <pardo.bsso@gmail.com> */
.name = "Genius TVGO AM11MCE",
.audio_clock = 0x00200000,
.tuner_type = TUNER_TNF_5335MF,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.gpiomask = 0xf000,
.inputs = {{
.name = name_tv_mono,
.vmux = 1,
.amux = LINE2,
.gpio = 0x0000,
.tv = 1,
}, {
.name = name_comp1,
.vmux = 3,
.amux = LINE1,
.gpio = 0x2000,
.tv = 1
}, {
.name = name_svideo,
.vmux = 8,
.amux = LINE1,
.gpio = 0x2000,
} },
.radio = {
.name = name_radio,
.amux = LINE2,
.gpio = 0x1000,
},
.mute = {
.name = name_mute,
.amux = LINE2,
.gpio = 0x6000,
},
},
}; };
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@ -4509,6 +4588,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x3502, /* whats the difference to 0x3306 ?*/ .subdevice = 0x3502, /* whats the difference to 0x3306 ?*/
.driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
},{ },{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5168,
.subdevice = 0x3307, /* FlyDVB-T Hybrid Mini PCI */
.driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
}, {
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x16be, .subvendor = 0x16be,
@ -4521,6 +4606,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x0008, .subdevice = 0x0008,
.driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO,
},{ },{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x16be,
.subdevice = 0x000d, /* triple CTX948_V1.1.1 */
.driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO,
}, {
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x1461, .subvendor = 0x1461,
@ -4843,7 +4934,13 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x4e42, .subvendor = 0x4e42,
.subdevice = 0x3502, .subdevice = 0x3502,
.driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
}, {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/
.subdevice = 0x0022,
.driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056,
},{ },{
/* --- boards without eeprom + subsystem ID --- */ /* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
@ -4995,6 +5092,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_BEHOLD_409: case SAA7134_BOARD_BEHOLD_409:
case SAA7134_BOARD_BEHOLD_505FM: case SAA7134_BOARD_BEHOLD_505FM:
case SAA7134_BOARD_BEHOLD_507_9FM: case SAA7134_BOARD_BEHOLD_507_9FM:
case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
dev->has_remote = SAA7134_REMOTE_GPIO; dev->has_remote = SAA7134_REMOTE_GPIO;
break; break;
case SAA7134_BOARD_FLYDVBS_LR300: case SAA7134_BOARD_FLYDVBS_LR300:
@ -5232,7 +5330,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
case SAA7134_BOARD_MEDION_MD8800_QUADRO: case SAA7134_BOARD_MEDION_MD8800_QUADRO:
case SAA7134_BOARD_AVERMEDIA_SUPER_007: case SAA7134_BOARD_AVERMEDIA_SUPER_007:
case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
/* this is a hybrid board, initialize to analog mode /* this is a hybrid board, initialize to analog mode
* and configure firmware eeprom address * and configure firmware eeprom address
*/ */

View File

@ -779,6 +779,21 @@ static struct tda1004x_config avermedia_super_007_config = {
.request_firmware = philips_tda1004x_request_firmware .request_firmware = philips_tda1004x_request_firmware
}; };
static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
.demod_address = 0x08,
.invert = 1,
.invert_oclk = 0,
.xtal_freq = TDA10046_XTAL_16M,
.agc_config = TDA10046_AGC_TDA827X,
.gpio_config = TDA10046_GP01_I,
.if_freq = TDA10046_FREQ_045,
.i2c_gate = 0x42,
.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 * special case: this card uses saa713x GPIO22 for the mode switch
*/ */
@ -826,6 +841,7 @@ static struct tda1004x_config ads_tech_duo_config = {
static struct tda10086_config flydvbs = { static struct tda10086_config flydvbs = {
.demod_address = 0x0e, .demod_address = 0x0e,
.invert = 0, .invert = 0,
.diseqc_tone = 0,
}; };
/* ================================================================== /* ==================================================================
@ -940,9 +956,9 @@ static int dvb_init(struct saa7134_dev *dev)
configure_tda827x_fe(dev, &tda827x_lifeview_config); configure_tda827x_fe(dev, &tda827x_lifeview_config);
break; break;
case SAA7134_BOARD_FLYDVB_TRIO: case SAA7134_BOARD_FLYDVB_TRIO:
if(! use_frontend) { //terrestrial if(! use_frontend) { /* terrestrial */
configure_tda827x_fe(dev, &lifeview_trio_config); configure_tda827x_fe(dev, &lifeview_trio_config);
} else { //satellite } else { /* satellite */
dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
if (dev->dvb.frontend) { if (dev->dvb.frontend) {
if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
@ -1007,8 +1023,9 @@ static int dvb_init(struct saa7134_dev *dev)
} }
break; break;
case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
dev->dvb.frontend = tda10046_attach(&medion_cardbus, dev->dvb.frontend = dvb_attach(tda10046_attach,
&dev->i2c_adap); &medion_cardbus,
&dev->i2c_adap);
if (dev->dvb.frontend) { if (dev->dvb.frontend) {
dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
@ -1044,6 +1061,9 @@ static int dvb_init(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_SUPER_007: case SAA7134_BOARD_AVERMEDIA_SUPER_007:
configure_tda827x_fe(dev, &avermedia_super_007_config); configure_tda827x_fe(dev, &avermedia_super_007_config);
break; break;
case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config);
break;
default: default:
wprintk("Huh? unknown DVB card?\n"); wprintk("Huh? unknown DVB card?\n");
break; break;

View File

@ -87,7 +87,7 @@ static int ts_open(struct inode *inode, struct file *file)
dprintk("open minor=%d\n",minor); dprintk("open minor=%d\n",minor);
err = -EBUSY; err = -EBUSY;
if (!mutex_trylock(&dev->empress_tsq.lock)) if (!mutex_trylock(&dev->empress_tsq.vb_lock))
goto done; goto done;
if (dev->empress_users) if (dev->empress_users)
goto done_up; goto done_up;
@ -101,7 +101,7 @@ static int ts_open(struct inode *inode, struct file *file)
err = 0; err = 0;
done_up: done_up:
mutex_unlock(&dev->empress_tsq.lock); mutex_unlock(&dev->empress_tsq.vb_lock);
done: done:
return err; return err;
} }
@ -110,7 +110,6 @@ static int ts_release(struct inode *inode, struct file *file)
{ {
struct saa7134_dev *dev = file->private_data; struct saa7134_dev *dev = file->private_data;
mutex_lock(&dev->empress_tsq.lock);
videobuf_stop(&dev->empress_tsq); videobuf_stop(&dev->empress_tsq);
videobuf_mmap_free(&dev->empress_tsq); videobuf_mmap_free(&dev->empress_tsq);
dev->empress_users--; dev->empress_users--;
@ -122,7 +121,6 @@ static int ts_release(struct inode *inode, struct file *file)
saa_writeb(SAA7134_AUDIO_MUTE_CTRL, saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
mutex_unlock(&dev->empress_tsq.lock);
return 0; return 0;
} }

View File

@ -406,6 +406,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
mask_keyup = 0x8000000; mask_keyup = 0x8000000;
polling = 50; //ms polling = 50; //ms
break; break;
case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
ir_codes = ir_codes_genius_tvgo_a11mce;
mask_keycode = 0xff;
mask_keydown = 0xf00000;
polling = 50; /* ms */
break;
} }
if (NULL == ir_codes) { if (NULL == ir_codes) {
printk("%s: Oops: IR config error [card=%d]\n", printk("%s: Oops: IR config error [card=%d]\n",

View File

@ -1414,21 +1414,17 @@ video_poll(struct file *file, struct poll_table_struct *wait)
if (!list_empty(&fh->cap.stream)) if (!list_empty(&fh->cap.stream))
buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream); buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
} else { } else {
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.vb_lock);
if (UNSET == fh->cap.read_off) { if (UNSET == fh->cap.read_off) {
/* need to capture a new frame */ /* need to capture a new frame */
if (res_locked(fh->dev,RESOURCE_VIDEO)) { if (res_locked(fh->dev,RESOURCE_VIDEO))
mutex_unlock(&fh->cap.lock); goto err;
return POLLERR; if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field))
} goto err;
if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) {
mutex_unlock(&fh->cap.lock);
return POLLERR;
}
fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
fh->cap.read_off = 0; fh->cap.read_off = 0;
} }
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.vb_lock);
buf = fh->cap.read_buf; buf = fh->cap.read_buf;
} }
@ -1440,6 +1436,10 @@ video_poll(struct file *file, struct poll_table_struct *wait)
buf->state == VIDEOBUF_ERROR) buf->state == VIDEOBUF_ERROR)
return POLLIN|POLLRDNORM; return POLLIN|POLLRDNORM;
return 0; return 0;
err:
mutex_unlock(&fh->cap.vb_lock);
return POLLERR;
} }
static int video_release(struct inode *inode, struct file *file) static int video_release(struct inode *inode, struct file *file)

View File

@ -252,6 +252,8 @@ struct saa7134_format {
#define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128 #define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128
#define SAA7134_BOARD_BEHOLD_607_9FM 129 #define SAA7134_BOARD_BEHOLD_607_9FM 129
#define SAA7134_BOARD_BEHOLD_M6 130 #define SAA7134_BOARD_BEHOLD_M6 130
#define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132
#define SAA7134_MAXBOARDS 8 #define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8 #define SAA7134_INPUT_MAX 8

View File

@ -225,7 +225,7 @@
/* Returns 0 if OK */ /* Returns 0 if OK */
int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val) static int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val)
{ {
int i = 0; int i = 0;
int tmpval = 0; int tmpval = 0;
@ -250,7 +250,7 @@ int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val)
return 0; return 0;
} }
int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val) static int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val)
{ {
int i = 0; int i = 0;
int tmpval = 0; int tmpval = 0;
@ -380,7 +380,7 @@ int stk_sensor_init(struct stk_camera *dev)
STK_ERROR("Strange error reading sensor ID\n"); STK_ERROR("Strange error reading sensor ID\n");
return -ENODEV; return -ENODEV;
} }
if (idh != 0x7F || idl != 0xA2) { if (idh != 0x7f || idl != 0xa2) {
STK_ERROR("Huh? you don't have a sensor from ovt\n"); STK_ERROR("Huh? you don't have a sensor from ovt\n");
return -ENODEV; return -ENODEV;
} }
@ -409,6 +409,19 @@ static struct regval ov_fmt_uyvy[] = {
{REG_COM15, COM15_R00FF }, {REG_COM15, COM15_R00FF },
{0xff, 0xff}, /* END MARKER */ {0xff, 0xff}, /* END MARKER */
}; };
/* V4L2_PIX_FMT_YUYV */
static struct regval ov_fmt_yuyv[] = {
{REG_TSLB, 0 },
{ 0x4f, 0x80 }, /* "matrix coefficient 1" */
{ 0x50, 0x80 }, /* "matrix coefficient 2" */
{ 0x51, 0 }, /* vb */
{ 0x52, 0x22 }, /* "matrix coefficient 4" */
{ 0x53, 0x5e }, /* "matrix coefficient 5" */
{ 0x54, 0x80 }, /* "matrix coefficient 6" */
{REG_COM13, COM13_UVSAT|COM13_CMATRIX},
{REG_COM15, COM15_R00FF },
{0xff, 0xff}, /* END MARKER */
};
/* V4L2_PIX_FMT_RGB565X rrrrrggg gggbbbbb */ /* V4L2_PIX_FMT_RGB565X rrrrrggg gggbbbbb */
static struct regval ov_fmt_rgbr[] = { static struct regval ov_fmt_rgbr[] = {
@ -519,6 +532,10 @@ int stk_sensor_configure(struct stk_camera *dev)
com7 |= COM7_YUV; com7 |= COM7_YUV;
rv = ov_fmt_uyvy; rv = ov_fmt_uyvy;
break; break;
case V4L2_PIX_FMT_YUYV:
com7 |= COM7_YUV;
rv = ov_fmt_yuyv;
break;
case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_RGB565:
com7 |= COM7_RGB; com7 |= COM7_RGB;
rv = ov_fmt_rgbp; rv = ov_fmt_rgbp;

View File

@ -63,7 +63,7 @@ static struct usb_device_id stkwebcam_table[] = {
}; };
MODULE_DEVICE_TABLE(usb, stkwebcam_table); MODULE_DEVICE_TABLE(usb, stkwebcam_table);
void stk_camera_cleanup(struct kref *kref) static void stk_camera_cleanup(struct kref *kref)
{ {
struct stk_camera *dev = to_stk_camera(kref); struct stk_camera *dev = to_stk_camera(kref);
@ -682,6 +682,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp)
return -ENXIO; return -ENXIO;
fp->private_data = vdev; fp->private_data = vdev;
kref_get(&dev->kref); kref_get(&dev->kref);
usb_autopm_get_interface(dev->interface);
return 0; return 0;
} }
@ -703,6 +704,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp)
} }
if (dev->owner != fp) { if (dev->owner != fp) {
usb_autopm_put_interface(dev->interface);
kref_put(&dev->kref, stk_camera_cleanup); kref_put(&dev->kref, stk_camera_cleanup);
return 0; return 0;
} }
@ -713,6 +715,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp)
dev->owner = NULL; dev->owner = NULL;
usb_autopm_put_interface(dev->interface);
kref_put(&dev->kref, stk_camera_cleanup); kref_put(&dev->kref, stk_camera_cleanup);
return 0; return 0;
@ -993,6 +996,10 @@ static int stk_vidioc_enum_fmt_cap(struct file *filp,
fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8; fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8;
strcpy(fmtd->description, "Raw bayer"); strcpy(fmtd->description, "Raw bayer");
break; break;
case 4:
fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
strcpy(fmtd->description, "yuv4:2:2");
break;
default: default:
return -EINVAL; return -EINVAL;
} }
@ -1048,6 +1055,7 @@ static int stk_vidioc_try_fmt_cap(struct file *filp,
case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_RGB565X: case V4L2_PIX_FMT_RGB565X:
case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_SBGGR8: case V4L2_PIX_FMT_SBGGR8:
break; break;
default: default:
@ -1080,6 +1088,42 @@ static int stk_vidioc_try_fmt_cap(struct file *filp,
return 0; return 0;
} }
static int stk_setup_format(struct stk_camera *dev)
{
int i = 0;
int depth;
if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)
depth = 1;
else
depth = 2;
while (stk_sizes[i].m != dev->vsettings.mode
&& i < ARRAY_SIZE(stk_sizes))
i++;
if (i == ARRAY_SIZE(stk_sizes)) {
STK_ERROR("Something is broken in %s\n", __FUNCTION__);
return -EFAULT;
}
/* This registers controls some timings, not sure of what. */
stk_camera_write_reg(dev, 0x001b, 0x0e);
if (dev->vsettings.mode == MODE_SXGA)
stk_camera_write_reg(dev, 0x001c, 0x0e);
else
stk_camera_write_reg(dev, 0x001c, 0x46);
/*
* Registers 0x0115 0x0114 are the size of each line (bytes),
* regs 0x0117 0x0116 are the heigth of the image.
*/
stk_camera_write_reg(dev, 0x0115,
((stk_sizes[i].w * depth) >> 8) & 0xff);
stk_camera_write_reg(dev, 0x0114,
(stk_sizes[i].w * depth) & 0xff);
stk_camera_write_reg(dev, 0x0117,
(stk_sizes[i].h >> 8) & 0xff);
stk_camera_write_reg(dev, 0x0116,
stk_sizes[i].h & 0xff);
return stk_sensor_configure(dev);
}
static int stk_vidioc_s_fmt_cap(struct file *filp, static int stk_vidioc_s_fmt_cap(struct file *filp,
void *priv, struct v4l2_format *fmtd) void *priv, struct v4l2_format *fmtd)
{ {
@ -1094,10 +1138,10 @@ static int stk_vidioc_s_fmt_cap(struct file *filp,
return -EBUSY; return -EBUSY;
if (dev->owner && dev->owner != filp) if (dev->owner && dev->owner != filp)
return -EBUSY; return -EBUSY;
dev->owner = filp;
ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd); ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd);
if (ret) if (ret)
return ret; return ret;
dev->owner = filp;
dev->vsettings.palette = fmtd->fmt.pix.pixelformat; dev->vsettings.palette = fmtd->fmt.pix.pixelformat;
stk_free_buffers(dev); stk_free_buffers(dev);
@ -1105,25 +1149,7 @@ static int stk_vidioc_s_fmt_cap(struct file *filp,
dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m; dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m;
stk_initialise(dev); stk_initialise(dev);
/* This registers controls some timings, not sure of what. */ return stk_setup_format(dev);
stk_camera_write_reg(dev, 0x001b, 0x0e);
if (dev->vsettings.mode == MODE_SXGA)
stk_camera_write_reg(dev, 0x001c, 0x0e);
else
stk_camera_write_reg(dev, 0x001c, 0x46);
/*
* Registers 0x0115 0x0114 are the size of each line (bytes),
* regs 0x0117 0x0116 are the heigth of the image.
*/
stk_camera_write_reg(dev, 0x0115,
(fmtd->fmt.pix.bytesperline >> 8) & 0xff);
stk_camera_write_reg(dev, 0x0114,
fmtd->fmt.pix.bytesperline & 0xff);
stk_camera_write_reg(dev, 0x0117,
(fmtd->fmt.pix.height >> 8) & 0xff);
stk_camera_write_reg(dev, 0x0116,
fmtd->fmt.pix.height & 0xff);
return stk_sensor_configure(dev);
} }
static int stk_vidioc_reqbufs(struct file *filp, static int stk_vidioc_reqbufs(struct file *filp,
@ -1288,6 +1314,9 @@ static struct file_operations v4l_stk_fops = {
.poll = v4l_stk_poll, .poll = v4l_stk_poll,
.mmap = v4l_stk_mmap, .mmap = v4l_stk_mmap,
.ioctl = video_ioctl2, .ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
#endif
.llseek = no_llseek .llseek = no_llseek
}; };
@ -1403,7 +1432,7 @@ static int stk_camera_probe(struct usb_interface *interface,
dev->vsettings.brightness = 0x7fff; dev->vsettings.brightness = 0x7fff;
dev->vsettings.palette = V4L2_PIX_FMT_RGB565; dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
dev->vsettings.mode = MODE_VGA; dev->vsettings.mode = MODE_VGA;
dev->frame_size = 640*480*2; dev->frame_size = 640 * 480 * 2;
INIT_LIST_HEAD(&dev->sio_avail); INIT_LIST_HEAD(&dev->sio_avail);
INIT_LIST_HEAD(&dev->sio_full); INIT_LIST_HEAD(&dev->sio_full);
@ -1417,6 +1446,7 @@ static int stk_camera_probe(struct usb_interface *interface,
} }
stk_create_sysfs_files(&dev->vdev); stk_create_sysfs_files(&dev->vdev);
usb_autopm_enable(dev->interface);
return 0; return 0;
} }
@ -1434,11 +1464,41 @@ static void stk_camera_disconnect(struct usb_interface *interface)
kref_put(&dev->kref, stk_camera_cleanup); kref_put(&dev->kref, stk_camera_cleanup);
} }
#ifdef CONFIG_PM
int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
{
struct stk_camera *dev = usb_get_intfdata(intf);
if (is_streaming(dev)) {
stk_stop_stream(dev);
/* yes, this is ugly */
set_streaming(dev);
}
return 0;
}
int stk_camera_resume(struct usb_interface *intf)
{
struct stk_camera *dev = usb_get_intfdata(intf);
if (!is_initialised(dev))
return 0;
unset_initialised(dev);
stk_initialise(dev);
stk_setup_format(dev);
if (is_streaming(dev))
stk_start_stream(dev);
return 0;
}
#endif
static struct usb_driver stk_camera_driver = { static struct usb_driver stk_camera_driver = {
.name = "stkwebcam", .name = "stkwebcam",
.probe = stk_camera_probe, .probe = stk_camera_probe,
.disconnect = stk_camera_disconnect, .disconnect = stk_camera_disconnect,
.id_table = stkwebcam_table, .id_table = stkwebcam_table,
#ifdef CONFIG_PM
.suspend = stk_camera_suspend,
.resume = stk_camera_resume,
#endif
}; };

View File

@ -79,6 +79,7 @@ enum stk_status {
#define unset_present(dev) ((dev)->status &= \ #define unset_present(dev) ((dev)->status &= \
~(S_PRESENT|S_INITIALISED|S_STREAMING)) ~(S_PRESENT|S_INITIALISED|S_STREAMING))
#define set_initialised(dev) ((dev)->status |= S_INITIALISED) #define set_initialised(dev) ((dev)->status |= S_INITIALISED)
#define unset_initialised(dev) ((dev)->status &= ~S_INITIALISED)
#define set_memallocd(dev) ((dev)->status |= S_MEMALLOCD) #define set_memallocd(dev) ((dev)->status |= S_MEMALLOCD)
#define unset_memallocd(dev) ((dev)->status &= ~S_MEMALLOCD) #define unset_memallocd(dev) ((dev)->status &= ~S_MEMALLOCD)
#define set_streaming(dev) ((dev)->status |= S_STREAMING) #define set_streaming(dev) ((dev)->status |= S_STREAMING)
@ -127,8 +128,6 @@ void stk_camera_delete(struct kref *);
int stk_camera_write_reg(struct stk_camera *, u16, u8); int stk_camera_write_reg(struct stk_camera *, u16, u8);
int stk_camera_read_reg(struct stk_camera *, u16, int *); int stk_camera_read_reg(struct stk_camera *, u16, int *);
int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val);
int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val);
int stk_sensor_init(struct stk_camera *); int stk_sensor_init(struct stk_camera *);
int stk_sensor_configure(struct stk_camera *); int stk_sensor_configure(struct stk_camera *);
int stk_sensor_sleep(struct stk_camera *dev); int stk_sensor_sleep(struct stk_camera *dev);

View File

@ -851,7 +851,7 @@ static int tcm825x_probe(struct i2c_client *client)
sensor->platform_data = client->dev.platform_data; sensor->platform_data = client->dev.platform_data;
if (sensor->platform_data == NULL if (sensor->platform_data == NULL
&& !sensor->platform_data->is_okay()) || !sensor->platform_data->is_okay())
return -ENODEV; return -ENODEV;
sensor->v4l2_int_device = &tcm825x_int_device; sensor->v4l2_int_device = &tcm825x_int_device;

View File

@ -1038,7 +1038,7 @@ static int tuner_resume(struct i2c_client *c)
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
LIST_HEAD(tuner_list); static LIST_HEAD(tuner_list);
/* Search for existing radio and/or TV tuners on the given I2C adapter. /* Search for existing radio and/or TV tuners on the given I2C adapter.
Note that when this function is called from tuner_probe you can be Note that when this function is called from tuner_probe you can be

View File

@ -754,6 +754,9 @@ skip_std_specific:
goto check_device; goto check_device;
} }
if (new_fw.type & FM)
goto check_device;
/* Load SCODE firmware, if exists */ /* Load SCODE firmware, if exists */
tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr); tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr);

View File

@ -1571,14 +1571,14 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip,
ctrl->value=chip->muted; ctrl->value=chip->muted;
return 0; return 0;
case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_VOLUME:
if (!desc->flags & CHIP_HAS_VOLUME) if (!(desc->flags & CHIP_HAS_VOLUME))
break; break;
ctrl->value = max(chip->left,chip->right); ctrl->value = max(chip->left,chip->right);
return 0; return 0;
case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BALANCE:
{ {
int volume; int volume;
if (!desc->flags & CHIP_HAS_VOLUME) if (!(desc->flags & CHIP_HAS_VOLUME))
break; break;
volume = max(chip->left,chip->right); volume = max(chip->left,chip->right);
if (volume) if (volume)
@ -1621,7 +1621,7 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip,
{ {
int volume,balance; int volume,balance;
if (!desc->flags & CHIP_HAS_VOLUME) if (!(desc->flags & CHIP_HAS_VOLUME))
break; break;
volume = max(chip->left,chip->right); volume = max(chip->left,chip->right);
@ -1642,7 +1642,7 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip,
case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BALANCE:
{ {
int volume, balance; int volume, balance;
if (!desc->flags & CHIP_HAS_VOLUME) if (!(desc->flags & CHIP_HAS_VOLUME))
break; break;
volume = max(chip->left,chip->right); volume = max(chip->left,chip->right);
@ -1702,7 +1702,7 @@ static int chip_command(struct i2c_client *client,
break; break;
case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BALANCE:
if (!desc->flags & CHIP_HAS_VOLUME) if (!(desc->flags & CHIP_HAS_VOLUME))
return -EINVAL; return -EINVAL;
break; break;
case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_BASS:

View File

@ -242,7 +242,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "TCL M2523_3DBH_E"}, { TUNER_ABSENT, "TCL M2523_3DBH_E"},
{ TUNER_ABSENT, "TCL M2523_3DIH_E"}, { TUNER_ABSENT, "TCL M2523_3DIH_E"},
{ TUNER_ABSENT, "TCL MFPE05_2_U"}, { TUNER_ABSENT, "TCL MFPE05_2_U"},
{ TUNER_ABSENT, "Philips FMD1216MEX"}, { TUNER_PHILIPS_FMD1216ME_MK3, "Philips FMD1216MEX"},
{ TUNER_ABSENT, "Philips FRH2036B"}, { TUNER_ABSENT, "Philips FRH2036B"},
{ TUNER_ABSENT, "Panasonic ENGF75_01GF"}, { TUNER_ABSENT, "Panasonic ENGF75_01GF"},
{ TUNER_ABSENT, "MaxLinear MXL5005"}, { TUNER_ABSENT, "MaxLinear MXL5005"},

View File

@ -56,7 +56,6 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <linux/video_decoder.h>
#define __OLD_VIDIOC_ /* To allow fixing old calls*/ #define __OLD_VIDIOC_ /* To allow fixing old calls*/
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
@ -82,108 +81,6 @@ MODULE_LICENSE("GPL");
*/ */
char *v4l2_norm_to_name(v4l2_std_id id)
{
char *name;
u32 myid = id;
/* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
64 bit comparations. So, on that architecture, with some gcc variants,
compilation fails. Currently, the max value is 30bit wide.
*/
BUG_ON(myid != id);
switch (myid) {
case V4L2_STD_PAL:
name="PAL"; break;
case V4L2_STD_PAL_BG:
name="PAL-BG"; break;
case V4L2_STD_PAL_DK:
name="PAL-DK"; break;
case V4L2_STD_PAL_B:
name="PAL-B"; break;
case V4L2_STD_PAL_B1:
name="PAL-B1"; break;
case V4L2_STD_PAL_G:
name="PAL-G"; break;
case V4L2_STD_PAL_H:
name="PAL-H"; break;
case V4L2_STD_PAL_I:
name="PAL-I"; break;
case V4L2_STD_PAL_D:
name="PAL-D"; break;
case V4L2_STD_PAL_D1:
name="PAL-D1"; break;
case V4L2_STD_PAL_K:
name="PAL-K"; break;
case V4L2_STD_PAL_M:
name="PAL-M"; break;
case V4L2_STD_PAL_N:
name="PAL-N"; break;
case V4L2_STD_PAL_Nc:
name="PAL-Nc"; break;
case V4L2_STD_PAL_60:
name="PAL-60"; break;
case V4L2_STD_NTSC:
name="NTSC"; break;
case V4L2_STD_NTSC_M:
name="NTSC-M"; break;
case V4L2_STD_NTSC_M_JP:
name="NTSC-M-JP"; break;
case V4L2_STD_NTSC_443:
name="NTSC-443"; break;
case V4L2_STD_NTSC_M_KR:
name="NTSC-M-KR"; break;
case V4L2_STD_SECAM:
name="SECAM"; break;
case V4L2_STD_SECAM_DK:
name="SECAM-DK"; break;
case V4L2_STD_SECAM_B:
name="SECAM-B"; break;
case V4L2_STD_SECAM_D:
name="SECAM-D"; break;
case V4L2_STD_SECAM_G:
name="SECAM-G"; break;
case V4L2_STD_SECAM_H:
name="SECAM-H"; break;
case V4L2_STD_SECAM_K:
name="SECAM-K"; break;
case V4L2_STD_SECAM_K1:
name="SECAM-K1"; break;
case V4L2_STD_SECAM_L:
name="SECAM-L"; break;
case V4L2_STD_SECAM_LC:
name="SECAM-LC"; break;
default:
name="Unknown"; break;
}
return name;
}
/* Fill in the fields of a v4l2_standard structure according to the
'id' and 'transmission' parameters. Returns negative on error. */
int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, char *name)
{
u32 index = vs->index;
memset(vs, 0, sizeof(struct v4l2_standard));
vs->index = index;
vs->id = id;
if (id & V4L2_STD_525_60) {
vs->frameperiod.numerator = 1001;
vs->frameperiod.denominator = 30000;
vs->framelines = 525;
} else {
vs->frameperiod.numerator = 1;
vs->frameperiod.denominator = 25;
vs->framelines = 625;
}
strlcpy(vs->name,name,sizeof(vs->name));
return 0;
}
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
/* priority handling */ /* priority handling */
@ -196,6 +93,7 @@ int v4l2_prio_init(struct v4l2_prio_state *global)
memset(global,0,sizeof(*global)); memset(global,0,sizeof(*global));
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_prio_init);
int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
enum v4l2_priority new) enum v4l2_priority new)
@ -211,11 +109,13 @@ int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
*local = new; *local = new;
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_prio_change);
int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local)
{ {
return v4l2_prio_change(global,local,V4L2_PRIORITY_DEFAULT); return v4l2_prio_change(global,local,V4L2_PRIORITY_DEFAULT);
} }
EXPORT_SYMBOL(v4l2_prio_open);
int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local) int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local)
{ {
@ -223,6 +123,7 @@ int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local)
atomic_dec(&global->prios[*local]); atomic_dec(&global->prios[*local]);
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_prio_close);
enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global)
{ {
@ -234,6 +135,7 @@ enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global)
return V4L2_PRIORITY_BACKGROUND; return V4L2_PRIORITY_BACKGROUND;
return V4L2_PRIORITY_UNSET; return V4L2_PRIORITY_UNSET;
} }
EXPORT_SYMBOL(v4l2_prio_max);
int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local) int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local)
{ {
@ -241,225 +143,7 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local)
return -EBUSY; return -EBUSY;
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_prio_check);
/* ----------------------------------------------------------------- */
/* some arrays for pretty-printing debug messages of enum types */
char *v4l2_field_names[] = {
[V4L2_FIELD_ANY] = "any",
[V4L2_FIELD_NONE] = "none",
[V4L2_FIELD_TOP] = "top",
[V4L2_FIELD_BOTTOM] = "bottom",
[V4L2_FIELD_INTERLACED] = "interlaced",
[V4L2_FIELD_SEQ_TB] = "seq-tb",
[V4L2_FIELD_SEQ_BT] = "seq-bt",
[V4L2_FIELD_ALTERNATE] = "alternate",
[V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
[V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
};
char *v4l2_type_names[] = {
[V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap",
[V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over",
[V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out",
[V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
[V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "video-out-over",
};
#define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown"
/* ------------------------------------------------------------------ */
/* debug help functions */
#ifdef CONFIG_VIDEO_V4L1_COMPAT
static const char *v4l1_ioctls[] = {
[_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP",
[_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN",
[_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN",
[_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER",
[_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER",
[_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT",
[_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT",
[_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE",
[_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN",
[_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN",
[_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF",
[_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF",
[_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY",
[_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ",
[_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ",
[_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO",
[_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO",
[_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC",
[_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE",
[_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF",
[_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT",
[_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE",
[_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE",
[_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE",
[_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
[_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO",
[_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
[_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT",
[_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT"
};
#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
#endif
static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
[_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
[_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
[_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
[_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
[_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
[_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
[_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
[_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
[_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
[_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
[_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
[_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
[_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
[_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
[_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
[_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
[_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
[_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
[_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
[_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
[_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
[_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
[_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
[_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
[_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
[_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
[_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
[_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
[_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
[_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
[_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
[_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
[_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
[_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
[_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
[_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
[_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
[_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
[_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
[_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
[_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
[_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
[_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
[_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
[_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
[_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
[_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
[_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
[_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
[_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
[_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS",
[_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS",
[_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS",
[_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS",
#if 1
[_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES",
[_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
[_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX",
[_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD",
[_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD",
[_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
[_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
[_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT",
#endif
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
static const char *v4l2_int_ioctls[] = {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
[_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES",
[_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS",
[_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM",
[_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT",
[_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT",
[_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT",
[_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE",
[_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO",
[_IOC_NR(DECODER_INIT)] = "DECODER_INIT",
[_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS",
[_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP",
#endif
[_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
[_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
[_IOC_NR(TUNER_SET_CONFIG)] = "TUNER_SET_CONFIG",
[_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE",
[_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET",
[_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
[_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE",
[_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA",
[_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA",
[_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ",
[_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY",
[_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING",
[_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING",
[_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING",
[_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING",
[_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)] = "VIDIOC_INT_S_CRYSTAL_FREQ",
[_IOC_NR(VIDIOC_INT_INIT)] = "VIDIOC_INT_INIT",
[_IOC_NR(VIDIOC_INT_G_STD_OUTPUT)] = "VIDIOC_INT_G_STD_OUTPUT",
[_IOC_NR(VIDIOC_INT_S_STD_OUTPUT)] = "VIDIOC_INT_S_STD_OUTPUT",
};
#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
/* Common ioctl debug function. This function can be used by
external ioctl messages as well as internal V4L ioctl */
void v4l_printk_ioctl(unsigned int cmd)
{
char *dir;
switch (_IOC_DIR(cmd)) {
case _IOC_NONE: dir = "--"; break;
case _IOC_READ: dir = "r-"; break;
case _IOC_WRITE: dir = "-w"; break;
case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
default: dir = "*ERR*"; break;
}
switch (_IOC_TYPE(cmd)) {
case 'd':
printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
(_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
break;
#ifdef CONFIG_VIDEO_V4L1_COMPAT
case 'v':
printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
(_IOC_NR(cmd) < V4L1_IOCTLS) ?
v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
break;
#endif
case 'V':
printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
(_IOC_NR(cmd) < V4L2_IOCTLS) ?
v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
break;
default:
printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
_IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
}
}
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
@ -488,6 +172,7 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
} }
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_ctrl_check);
/* Returns NULL or a character pointer array containing the menu for /* Returns NULL or a character pointer array containing the menu for
the given control ID. The pointer array ends with a NULL pointer. the given control ID. The pointer array ends with a NULL pointer.
@ -648,6 +333,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
return NULL; return NULL;
} }
} }
EXPORT_SYMBOL(v4l2_ctrl_get_menu);
/* Fill in a struct v4l2_queryctrl */ /* Fill in a struct v4l2_queryctrl */
int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
@ -770,6 +456,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste
snprintf(qctrl->name, sizeof(qctrl->name), name); snprintf(qctrl->name, sizeof(qctrl->name), name);
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_ctrl_query_fill);
/* Fill in a struct v4l2_queryctrl with standard values based on /* Fill in a struct v4l2_queryctrl with standard values based on
the control ID. */ the control ID. */
@ -904,6 +591,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
return -EINVAL; return -EINVAL;
} }
} }
EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
the menu. The qctrl pointer may be NULL, in which case it is ignored. */ the menu. The qctrl pointer may be NULL, in which case it is ignored. */
@ -922,6 +610,7 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc
qmenu->reserved = 0; qmenu->reserved = 0;
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_ctrl_query_menu);
/* ctrl_classes points to an array of u32 pointers, the last element is /* ctrl_classes points to an array of u32 pointers, the last element is
a NULL pointer. Each u32 array is a 0-terminated array of control IDs. a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
@ -972,7 +661,20 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
return 0; return 0;
return **ctrl_classes; return **ctrl_classes;
} }
EXPORT_SYMBOL(v4l2_ctrl_next);
int v4l2_chip_match_host(u32 match_type, u32 match_chip)
{
switch (match_type) {
case V4L2_CHIP_MATCH_HOST:
return match_chip == 0;
default:
return 0;
}
}
EXPORT_SYMBOL(v4l2_chip_match_host);
#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip) int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip)
{ {
switch (match_type) { switch (match_type) {
@ -984,6 +686,7 @@ int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_c
return 0; return 0;
} }
} }
EXPORT_SYMBOL(v4l2_chip_match_i2c_client);
int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip, int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip,
u32 ident, u32 revision) u32 ident, u32 revision)
@ -1000,16 +703,7 @@ int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chi
} }
return 0; return 0;
} }
EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
int v4l2_chip_match_host(u32 match_type, u32 match_chip)
{
switch (match_type) {
case V4L2_CHIP_MATCH_HOST:
return match_chip == 0;
default:
return 0;
}
}
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
@ -1038,38 +732,5 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver
} }
return err != -ENOMEM ? 0 : err; return err != -ENOMEM ? 0 : err;
} }
/* ----------------------------------------------------------------- */
EXPORT_SYMBOL(v4l2_norm_to_name);
EXPORT_SYMBOL(v4l2_video_std_construct);
EXPORT_SYMBOL(v4l2_prio_init);
EXPORT_SYMBOL(v4l2_prio_change);
EXPORT_SYMBOL(v4l2_prio_open);
EXPORT_SYMBOL(v4l2_prio_close);
EXPORT_SYMBOL(v4l2_prio_max);
EXPORT_SYMBOL(v4l2_prio_check);
EXPORT_SYMBOL(v4l2_field_names);
EXPORT_SYMBOL(v4l2_type_names);
EXPORT_SYMBOL(v4l_printk_ioctl);
EXPORT_SYMBOL(v4l2_ctrl_next);
EXPORT_SYMBOL(v4l2_ctrl_check);
EXPORT_SYMBOL(v4l2_ctrl_get_menu);
EXPORT_SYMBOL(v4l2_ctrl_query_menu);
EXPORT_SYMBOL(v4l2_ctrl_query_fill);
EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
EXPORT_SYMBOL(v4l2_chip_match_i2c_client);
EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
EXPORT_SYMBOL(v4l2_chip_match_host);
EXPORT_SYMBOL(v4l2_i2c_attach); EXPORT_SYMBOL(v4l2_i2c_attach);
#endif
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@ -147,7 +147,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
/* Having implementations for abstract methods are mandatory */ /* Having implementations for abstract methods are mandatory */
BUG_ON(!q->int_ops); BUG_ON(!q->int_ops);
mutex_init(&q->lock); mutex_init(&q->vb_lock);
INIT_LIST_HEAD(&q->stream); INIT_LIST_HEAD(&q->stream);
} }
@ -189,7 +189,7 @@ int videobuf_queue_is_busy(struct videobuf_queue *q)
return 0; return 0;
} }
/* Locking: Caller holds q->lock */ /* Locking: Caller holds q->vb_lock */
void videobuf_queue_cancel(struct videobuf_queue *q) void videobuf_queue_cancel(struct videobuf_queue *q)
{ {
unsigned long flags = 0; unsigned long flags = 0;
@ -220,7 +220,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
/* Locking: Caller holds q->lock */ /* Locking: Caller holds q->vb_lock */
enum v4l2_field videobuf_next_field(struct videobuf_queue *q) enum v4l2_field videobuf_next_field(struct videobuf_queue *q)
{ {
enum v4l2_field field = q->field; enum v4l2_field field = q->field;
@ -239,7 +239,7 @@ enum v4l2_field videobuf_next_field(struct videobuf_queue *q)
return field; return field;
} }
/* Locking: Caller holds q->lock */ /* Locking: Caller holds q->vb_lock */
static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
struct videobuf_buffer *vb, enum v4l2_buf_type type) struct videobuf_buffer *vb, enum v4l2_buf_type type)
{ {
@ -295,7 +295,7 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
b->sequence = vb->field_count >> 1; b->sequence = vb->field_count >> 1;
} }
/* Locking: Caller holds q->lock */ /* Locking: Caller holds q->vb_lock */
static int __videobuf_mmap_free(struct videobuf_queue *q) static int __videobuf_mmap_free(struct videobuf_queue *q)
{ {
int i; int i;
@ -328,13 +328,13 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
int videobuf_mmap_free(struct videobuf_queue *q) int videobuf_mmap_free(struct videobuf_queue *q)
{ {
int ret; int ret;
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
ret = __videobuf_mmap_free(q); ret = __videobuf_mmap_free(q);
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return ret; return ret;
} }
/* Locking: Caller holds q->lock */ /* Locking: Caller holds q->vb_lock */
static int __videobuf_mmap_setup(struct videobuf_queue *q, static int __videobuf_mmap_setup(struct videobuf_queue *q,
unsigned int bcount, unsigned int bsize, unsigned int bcount, unsigned int bsize,
enum v4l2_memory memory) enum v4l2_memory memory)
@ -384,9 +384,9 @@ int videobuf_mmap_setup(struct videobuf_queue *q,
enum v4l2_memory memory) enum v4l2_memory memory)
{ {
int ret; int ret;
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
ret = __videobuf_mmap_setup(q, bcount, bsize, memory); ret = __videobuf_mmap_setup(q, bcount, bsize, memory);
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return ret; return ret;
} }
@ -408,7 +408,7 @@ int videobuf_reqbufs(struct videobuf_queue *q,
return -EINVAL; return -EINVAL;
} }
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
if (req->type != q->type) { if (req->type != q->type) {
dprintk(1, "reqbufs: queue type invalid\n"); dprintk(1, "reqbufs: queue type invalid\n");
retval = -EINVAL; retval = -EINVAL;
@ -444,7 +444,7 @@ int videobuf_reqbufs(struct videobuf_queue *q,
req->count = retval; req->count = retval;
done: done:
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return retval; return retval;
} }
@ -452,7 +452,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
{ {
int ret = -EINVAL; int ret = -EINVAL;
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
if (unlikely(b->type != q->type)) { if (unlikely(b->type != q->type)) {
dprintk(1, "querybuf: Wrong type.\n"); dprintk(1, "querybuf: Wrong type.\n");
goto done; goto done;
@ -470,7 +470,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
ret = 0; ret = 0;
done: done:
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return ret; return ret;
} }
@ -487,7 +487,7 @@ int videobuf_qbuf(struct videobuf_queue *q,
if (b->memory == V4L2_MEMORY_MMAP) if (b->memory == V4L2_MEMORY_MMAP)
down_read(&current->mm->mmap_sem); down_read(&current->mm->mmap_sem);
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
retval = -EBUSY; retval = -EBUSY;
if (q->reading) { if (q->reading) {
dprintk(1, "qbuf: Reading running...\n"); dprintk(1, "qbuf: Reading running...\n");
@ -573,7 +573,7 @@ int videobuf_qbuf(struct videobuf_queue *q,
retval = 0; retval = 0;
done: done:
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
if (b->memory == V4L2_MEMORY_MMAP) if (b->memory == V4L2_MEMORY_MMAP)
up_read(&current->mm->mmap_sem); up_read(&current->mm->mmap_sem);
@ -589,7 +589,7 @@ int videobuf_dqbuf(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
retval = -EBUSY; retval = -EBUSY;
if (q->reading) { if (q->reading) {
dprintk(1, "dqbuf: Reading running...\n"); dprintk(1, "dqbuf: Reading running...\n");
@ -632,7 +632,7 @@ int videobuf_dqbuf(struct videobuf_queue *q,
videobuf_status(q, b, buf, q->type); videobuf_status(q, b, buf, q->type);
done: done:
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return retval; return retval;
} }
@ -642,7 +642,7 @@ int videobuf_streamon(struct videobuf_queue *q)
unsigned long flags = 0; unsigned long flags = 0;
int retval; int retval;
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
retval = -EBUSY; retval = -EBUSY;
if (q->reading) if (q->reading)
goto done; goto done;
@ -659,11 +659,11 @@ int videobuf_streamon(struct videobuf_queue *q)
spin_unlock_irqrestore(q->irqlock, flags); spin_unlock_irqrestore(q->irqlock, flags);
done: done:
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return retval; return retval;
} }
/* Locking: Caller holds q->lock */ /* Locking: Caller holds q->vb_lock */
static int __videobuf_streamoff(struct videobuf_queue *q) static int __videobuf_streamoff(struct videobuf_queue *q)
{ {
if (!q->streaming) if (!q->streaming)
@ -679,14 +679,14 @@ int videobuf_streamoff(struct videobuf_queue *q)
{ {
int retval; int retval;
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
retval = __videobuf_streamoff(q); retval = __videobuf_streamoff(q);
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return retval; return retval;
} }
/* Locking: Caller holds q->lock */ /* Locking: Caller holds q->vb_lock */
static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
char __user *data, char __user *data,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
@ -745,7 +745,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
nbufs = 1; size = 0; nbufs = 1; size = 0;
q->ops->buf_setup(q, &nbufs, &size); q->ops->buf_setup(q, &nbufs, &size);
@ -817,11 +817,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
} }
done: done:
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return retval; return retval;
} }
/* Locking: Caller holds q->lock */ /* Locking: Caller holds q->vb_lock */
static int __videobuf_read_start(struct videobuf_queue *q) static int __videobuf_read_start(struct videobuf_queue *q)
{ {
enum v4l2_field field; enum v4l2_field field;
@ -882,23 +882,23 @@ int videobuf_read_start(struct videobuf_queue *q)
{ {
int rc; int rc;
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
rc = __videobuf_read_start(q); rc = __videobuf_read_start(q);
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return rc; return rc;
} }
void videobuf_read_stop(struct videobuf_queue *q) void videobuf_read_stop(struct videobuf_queue *q)
{ {
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
__videobuf_read_stop(q); __videobuf_read_stop(q);
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
} }
void videobuf_stop(struct videobuf_queue *q) void videobuf_stop(struct videobuf_queue *q)
{ {
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
if (q->streaming) if (q->streaming)
__videobuf_streamoff(q); __videobuf_streamoff(q);
@ -906,7 +906,7 @@ void videobuf_stop(struct videobuf_queue *q)
if (q->reading) if (q->reading)
__videobuf_read_stop(q); __videobuf_read_stop(q);
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
} }
@ -920,7 +920,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
dprintk(2, "%s\n", __FUNCTION__); dprintk(2, "%s\n", __FUNCTION__);
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
retval = -EBUSY; retval = -EBUSY;
if (q->streaming) if (q->streaming)
goto done; goto done;
@ -980,7 +980,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
} }
done: done:
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return retval; return retval;
} }
@ -991,7 +991,7 @@ unsigned int videobuf_poll_stream(struct file *file,
struct videobuf_buffer *buf = NULL; struct videobuf_buffer *buf = NULL;
unsigned int rc = 0; unsigned int rc = 0;
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
if (q->streaming) { if (q->streaming) {
if (!list_empty(&q->stream)) if (!list_empty(&q->stream))
buf = list_entry(q->stream.next, buf = list_entry(q->stream.next,
@ -1019,7 +1019,7 @@ unsigned int videobuf_poll_stream(struct file *file,
buf->state == VIDEOBUF_ERROR) buf->state == VIDEOBUF_ERROR)
rc = POLLIN|POLLRDNORM; rc = POLLIN|POLLRDNORM;
} }
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return rc; return rc;
} }
@ -1030,10 +1030,10 @@ int videobuf_mmap_mapper(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
retval = CALL(q, mmap_mapper, q, vma); retval = CALL(q, mmap_mapper, q, vma);
q->is_mmapped = 1; q->is_mmapped = 1;
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
return retval; return retval;
} }

View File

@ -356,7 +356,7 @@ videobuf_vm_close(struct vm_area_struct *vma)
map->count--; map->count--;
if (0 == map->count) { if (0 == map->count) {
dprintk(1,"munmap %p q=%p\n",map,q); dprintk(1,"munmap %p q=%p\n",map,q);
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
for (i = 0; i < VIDEO_MAX_FRAME; i++) { for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i]) if (NULL == q->bufs[i])
continue; continue;
@ -373,7 +373,7 @@ videobuf_vm_close(struct vm_area_struct *vma)
q->bufs[i]->baddr = 0; q->bufs[i]->baddr = 0;
q->ops->buf_release(q,q->bufs[i]); q->ops->buf_release(q,q->bufs[i]);
} }
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
kfree(map); kfree(map);
} }
return; return;

View File

@ -70,7 +70,7 @@ videobuf_vm_close(struct vm_area_struct *vma)
map->count--; map->count--;
if (0 == map->count) { if (0 == map->count) {
dprintk(1,"munmap %p q=%p\n",map,q); dprintk(1,"munmap %p q=%p\n",map,q);
mutex_lock(&q->lock); mutex_lock(&q->vb_lock);
for (i = 0; i < VIDEO_MAX_FRAME; i++) { for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i]) if (NULL == q->bufs[i])
continue; continue;
@ -83,7 +83,7 @@ videobuf_vm_close(struct vm_area_struct *vma)
q->bufs[i]->map = NULL; q->bufs[i]->map = NULL;
q->bufs[i]->baddr = 0; q->bufs[i]->baddr = 0;
} }
mutex_unlock(&q->lock); mutex_unlock(&q->vb_lock);
kfree(map); kfree(map);
} }
return; return;
@ -107,7 +107,7 @@ static struct vm_operations_struct videobuf_vm_ops =
static void *__videobuf_alloc(size_t size) static void *__videobuf_alloc(size_t size)
{ {
struct videbuf_vmalloc_memory *mem; struct videobuf_vmalloc_memory *mem;
struct videobuf_buffer *vb; struct videobuf_buffer *vb;
vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
@ -127,9 +127,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
struct v4l2_framebuffer *fbuf) struct v4l2_framebuffer *fbuf)
{ {
int pages; int pages;
struct videobuf_vmalloc_memory *mem=vb->priv;
struct videbuf_vmalloc_memory *mem=vb->priv;
BUG_ON(!mem); BUG_ON(!mem);
@ -195,7 +193,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
static int __videobuf_mmap_mapper(struct videobuf_queue *q, static int __videobuf_mmap_mapper(struct videobuf_queue *q,
struct vm_area_struct *vma) struct vm_area_struct *vma)
{ {
struct videbuf_vmalloc_memory *mem; struct videobuf_vmalloc_memory *mem;
struct videobuf_mapping *map; struct videobuf_mapping *map;
unsigned int first; unsigned int first;
int retval; int retval;
@ -267,7 +265,7 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q,
char __user *data, size_t count, char __user *data, size_t count,
int nonblocking ) int nonblocking )
{ {
struct videbuf_vmalloc_memory *mem=q->read_buf->priv; struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
BUG_ON (!mem); BUG_ON (!mem);
MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
@ -288,7 +286,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
int vbihack, int nonblocking ) int vbihack, int nonblocking )
{ {
unsigned int *fc; unsigned int *fc;
struct videbuf_vmalloc_memory *mem=q->read_buf->priv; struct videobuf_vmalloc_memory *mem=q->read_buf->priv;
BUG_ON (!mem); BUG_ON (!mem);
MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
@ -341,7 +339,7 @@ EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
void *videobuf_to_vmalloc (struct videobuf_buffer *buf) void *videobuf_to_vmalloc (struct videobuf_buffer *buf)
{ {
struct videbuf_vmalloc_memory *mem=buf->priv; struct videobuf_vmalloc_memory *mem=buf->priv;
BUG_ON (!mem); BUG_ON (!mem);
MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
@ -351,7 +349,7 @@ EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
void videobuf_vmalloc_free (struct videobuf_buffer *buf) void videobuf_vmalloc_free (struct videobuf_buffer *buf)
{ {
struct videbuf_vmalloc_memory *mem=buf->priv; struct videobuf_vmalloc_memory *mem=buf->priv;
BUG_ON (!mem); BUG_ON (!mem);
MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);

View File

@ -46,10 +46,373 @@
#include <linux/videodev.h> #include <linux/videodev.h>
#endif #endif
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <linux/video_decoder.h>
#define VIDEO_NUM_DEVICES 256 #define VIDEO_NUM_DEVICES 256
#define VIDEO_NAME "video4linux" #define VIDEO_NAME "video4linux"
/* video4linux standard ID conversion to standard name
*/
char *v4l2_norm_to_name(v4l2_std_id id)
{
char *name;
u32 myid = id;
/* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
64 bit comparations. So, on that architecture, with some gcc
variants, compilation fails. Currently, the max value is 30bit wide.
*/
BUG_ON(myid != id);
switch (myid) {
case V4L2_STD_PAL:
name = "PAL";
break;
case V4L2_STD_PAL_BG:
name = "PAL-BG";
break;
case V4L2_STD_PAL_DK:
name = "PAL-DK";
break;
case V4L2_STD_PAL_B:
name = "PAL-B";
break;
case V4L2_STD_PAL_B1:
name = "PAL-B1";
break;
case V4L2_STD_PAL_G:
name = "PAL-G";
break;
case V4L2_STD_PAL_H:
name = "PAL-H";
break;
case V4L2_STD_PAL_I:
name = "PAL-I";
break;
case V4L2_STD_PAL_D:
name = "PAL-D";
break;
case V4L2_STD_PAL_D1:
name = "PAL-D1";
break;
case V4L2_STD_PAL_K:
name = "PAL-K";
break;
case V4L2_STD_PAL_M:
name = "PAL-M";
break;
case V4L2_STD_PAL_N:
name = "PAL-N";
break;
case V4L2_STD_PAL_Nc:
name = "PAL-Nc";
break;
case V4L2_STD_PAL_60:
name = "PAL-60";
break;
case V4L2_STD_NTSC:
name = "NTSC";
break;
case V4L2_STD_NTSC_M:
name = "NTSC-M";
break;
case V4L2_STD_NTSC_M_JP:
name = "NTSC-M-JP";
break;
case V4L2_STD_NTSC_443:
name = "NTSC-443";
break;
case V4L2_STD_NTSC_M_KR:
name = "NTSC-M-KR";
break;
case V4L2_STD_SECAM:
name = "SECAM";
break;
case V4L2_STD_SECAM_DK:
name = "SECAM-DK";
break;
case V4L2_STD_SECAM_B:
name = "SECAM-B";
break;
case V4L2_STD_SECAM_D:
name = "SECAM-D";
break;
case V4L2_STD_SECAM_G:
name = "SECAM-G";
break;
case V4L2_STD_SECAM_H:
name = "SECAM-H";
break;
case V4L2_STD_SECAM_K:
name = "SECAM-K";
break;
case V4L2_STD_SECAM_K1:
name = "SECAM-K1";
break;
case V4L2_STD_SECAM_L:
name = "SECAM-L";
break;
case V4L2_STD_SECAM_LC:
name = "SECAM-LC";
break;
default:
name = "Unknown";
break;
}
return name;
}
EXPORT_SYMBOL(v4l2_norm_to_name);
/* Fill in the fields of a v4l2_standard structure according to the
'id' and 'transmission' parameters. Returns negative on error. */
int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, char *name)
{
u32 index = vs->index;
memset(vs, 0, sizeof(struct v4l2_standard));
vs->index = index;
vs->id = id;
if (id & V4L2_STD_525_60) {
vs->frameperiod.numerator = 1001;
vs->frameperiod.denominator = 30000;
vs->framelines = 525;
} else {
vs->frameperiod.numerator = 1;
vs->frameperiod.denominator = 25;
vs->framelines = 625;
}
strlcpy(vs->name, name, sizeof(vs->name));
return 0;
}
EXPORT_SYMBOL(v4l2_video_std_construct);
/* ----------------------------------------------------------------- */
/* some arrays for pretty-printing debug messages of enum types */
char *v4l2_field_names[] = {
[V4L2_FIELD_ANY] = "any",
[V4L2_FIELD_NONE] = "none",
[V4L2_FIELD_TOP] = "top",
[V4L2_FIELD_BOTTOM] = "bottom",
[V4L2_FIELD_INTERLACED] = "interlaced",
[V4L2_FIELD_SEQ_TB] = "seq-tb",
[V4L2_FIELD_SEQ_BT] = "seq-bt",
[V4L2_FIELD_ALTERNATE] = "alternate",
[V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
[V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
};
EXPORT_SYMBOL(v4l2_field_names);
char *v4l2_type_names[] = {
[V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap",
[V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over",
[V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out",
[V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
[V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "video-out-over",
};
EXPORT_SYMBOL(v4l2_type_names);
static char *v4l2_memory_names[] = {
[V4L2_MEMORY_MMAP] = "mmap",
[V4L2_MEMORY_USERPTR] = "userptr",
[V4L2_MEMORY_OVERLAY] = "overlay",
};
#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
arr[a] : "unknown")
/* ------------------------------------------------------------------ */
/* debug help functions */
#ifdef CONFIG_VIDEO_V4L1_COMPAT
static const char *v4l1_ioctls[] = {
[_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP",
[_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN",
[_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN",
[_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER",
[_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER",
[_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT",
[_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT",
[_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE",
[_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN",
[_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN",
[_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF",
[_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF",
[_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY",
[_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ",
[_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ",
[_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO",
[_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO",
[_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC",
[_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE",
[_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF",
[_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT",
[_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE",
[_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE",
[_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE",
[_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
[_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO",
[_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
[_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT",
[_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT"
};
#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
#endif
static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
[_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
[_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
[_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
[_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
[_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
[_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
[_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
[_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
[_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
[_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
[_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
[_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
[_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
[_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
[_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
[_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
[_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
[_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
[_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
[_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
[_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
[_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
[_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
[_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
[_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
[_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
[_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
[_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
[_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
[_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
[_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
[_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
[_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
[_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
[_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
[_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
[_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
[_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
[_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
[_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
[_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
[_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
[_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
[_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
[_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
[_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
[_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
[_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
[_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
[_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
[_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS",
[_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS",
[_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS",
[_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS",
#if 1
[_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES",
[_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
[_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX",
[_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD",
[_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD",
[_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
[_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
[_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT",
#endif
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
static const char *v4l2_int_ioctls[] = {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
[_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES",
[_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS",
[_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM",
[_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT",
[_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT",
[_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT",
[_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE",
[_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO",
[_IOC_NR(DECODER_INIT)] = "DECODER_INIT",
[_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS",
[_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP",
#endif
[_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
[_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
[_IOC_NR(TUNER_SET_CONFIG)] = "TUNER_SET_CONFIG",
[_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE",
[_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET",
[_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
[_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE",
[_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA",
[_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA",
[_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ",
[_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY",
[_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING",
[_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING",
[_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING",
[_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING",
[_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)] = "VIDIOC_INT_S_CRYSTAL_FREQ",
[_IOC_NR(VIDIOC_INT_INIT)] = "VIDIOC_INT_INIT",
[_IOC_NR(VIDIOC_INT_G_STD_OUTPUT)] = "VIDIOC_INT_G_STD_OUTPUT",
[_IOC_NR(VIDIOC_INT_S_STD_OUTPUT)] = "VIDIOC_INT_S_STD_OUTPUT",
};
#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
/* Common ioctl debug function. This function can be used by
external ioctl messages as well as internal V4L ioctl */
void v4l_printk_ioctl(unsigned int cmd)
{
char *dir;
switch (_IOC_DIR(cmd)) {
case _IOC_NONE: dir = "--"; break;
case _IOC_READ: dir = "r-"; break;
case _IOC_WRITE: dir = "-w"; break;
case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
default: dir = "*ERR*"; break;
}
switch (_IOC_TYPE(cmd)) {
case 'd':
printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
(_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
break;
#ifdef CONFIG_VIDEO_V4L1_COMPAT
case 'v':
printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
(_IOC_NR(cmd) < V4L1_IOCTLS) ?
v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
break;
#endif
case 'V':
printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
(_IOC_NR(cmd) < V4L2_IOCTLS) ?
v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
break;
default:
printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
_IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
}
}
EXPORT_SYMBOL(v4l_printk_ioctl);
/* /*
* sysfs stuff * sysfs stuff
*/ */
@ -69,11 +432,13 @@ struct video_device *video_device_alloc(void)
vfd = kzalloc(sizeof(*vfd),GFP_KERNEL); vfd = kzalloc(sizeof(*vfd),GFP_KERNEL);
return vfd; return vfd;
} }
EXPORT_SYMBOL(video_device_alloc);
void video_device_release(struct video_device *vfd) void video_device_release(struct video_device *vfd)
{ {
kfree(vfd); kfree(vfd);
} }
EXPORT_SYMBOL(video_device_release);
static void video_release(struct device *cd) static void video_release(struct device *cd)
{ {
@ -110,6 +475,7 @@ struct video_device* video_devdata(struct file *file)
{ {
return video_device[iminor(file->f_path.dentry->d_inode)]; return video_device[iminor(file->f_path.dentry->d_inode)];
} }
EXPORT_SYMBOL(video_devdata);
/* /*
* Open a video device - FIXME: Obsoleted * Open a video device - FIXME: Obsoleted
@ -278,6 +644,7 @@ out:
kfree(mbuf); kfree(mbuf);
return err; return err;
} }
EXPORT_SYMBOL(video_usercopy);
/* /*
* open/release helper functions -- handle exclusive opens * open/release helper functions -- handle exclusive opens
@ -297,6 +664,7 @@ int video_exclusive_open(struct inode *inode, struct file *file)
mutex_unlock(&vfl->lock); mutex_unlock(&vfl->lock);
return retval; return retval;
} }
EXPORT_SYMBOL(video_exclusive_open);
int video_exclusive_release(struct inode *inode, struct file *file) int video_exclusive_release(struct inode *inode, struct file *file)
{ {
@ -305,41 +673,7 @@ int video_exclusive_release(struct inode *inode, struct file *file)
vfl->users--; vfl->users--;
return 0; return 0;
} }
EXPORT_SYMBOL(video_exclusive_release);
static char *v4l2_memory_names[] = {
[V4L2_MEMORY_MMAP] = "mmap",
[V4L2_MEMORY_USERPTR] = "userptr",
[V4L2_MEMORY_OVERLAY] = "overlay",
};
/* FIXME: Those stuff are replicated also on v4l2-common.c */
static char *v4l2_type_names_FIXME[] = {
[V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap",
[V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over",
[V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out",
[V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
[V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-capture",
[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "video-out-over",
[V4L2_BUF_TYPE_PRIVATE] = "private",
};
static char *v4l2_field_names_FIXME[] = {
[V4L2_FIELD_ANY] = "any",
[V4L2_FIELD_NONE] = "none",
[V4L2_FIELD_TOP] = "top",
[V4L2_FIELD_BOTTOM] = "bottom",
[V4L2_FIELD_INTERLACED] = "interlaced",
[V4L2_FIELD_SEQ_TB] = "seq-tb",
[V4L2_FIELD_SEQ_BT] = "seq-bt",
[V4L2_FIELD_ALTERNATE] = "alternate",
[V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
[V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
};
#define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown"
static void dbgbuf(unsigned int cmd, struct video_device *vfd, static void dbgbuf(unsigned int cmd, struct video_device *vfd,
struct v4l2_buffer *p) struct v4l2_buffer *p)
@ -354,10 +688,10 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
(int)(p->timestamp.tv_sec%60), (int)(p->timestamp.tv_sec%60),
p->timestamp.tv_usec, p->timestamp.tv_usec,
p->index, p->index,
prt_names(p->type,v4l2_type_names_FIXME), prt_names(p->type, v4l2_type_names),
p->bytesused,p->flags, p->bytesused, p->flags,
p->field,p->sequence, p->field, p->sequence,
prt_names(p->memory,v4l2_memory_names), prt_names(p->memory, v4l2_memory_names),
p->m.userptr, p->length); p->m.userptr, p->length);
dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "
"flags=0x%08d, frames=%d, userbits=0x%08x\n", "flags=0x%08d, frames=%d, userbits=0x%08x\n",
@ -382,8 +716,8 @@ static inline void v4l_print_pix_fmt (struct video_device *vfd,
(fmt->pixelformat >> 8) & 0xff, (fmt->pixelformat >> 8) & 0xff,
(fmt->pixelformat >> 16) & 0xff, (fmt->pixelformat >> 16) & 0xff,
(fmt->pixelformat >> 24) & 0xff, (fmt->pixelformat >> 24) & 0xff,
prt_names(fmt->field,v4l2_field_names_FIXME), prt_names(fmt->field, v4l2_field_names),
fmt->bytesperline,fmt->sizeimage,fmt->colorspace); fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
}; };
@ -597,7 +931,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
/* FIXME: Should be one dump per type */ /* FIXME: Should be one dump per type */
dbgarg (cmd, "type=%s\n", prt_names(type, dbgarg (cmd, "type=%s\n", prt_names(type,
v4l2_type_names_FIXME)); v4l2_type_names));
switch (type) { switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@ -650,7 +984,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
/* FIXME: Should be one dump per type */ /* FIXME: Should be one dump per type */
dbgarg (cmd, "type=%s\n", prt_names(f->type, dbgarg (cmd, "type=%s\n", prt_names(f->type,
v4l2_type_names_FIXME)); v4l2_type_names));
switch (f->type) { switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@ -702,7 +1036,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
/* FIXME: Should be one dump per type */ /* FIXME: Should be one dump per type */
dbgarg (cmd, "type=%s\n", prt_names(f->type, dbgarg (cmd, "type=%s\n", prt_names(f->type,
v4l2_type_names_FIXME)); v4l2_type_names));
switch (f->type) { switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (vfd->vidioc_try_fmt_cap) if (vfd->vidioc_try_fmt_cap)
@ -768,8 +1102,8 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_reqbufs(file, fh, p); ret=vfd->vidioc_reqbufs(file, fh, p);
dbgarg (cmd, "count=%d, type=%s, memory=%s\n", dbgarg (cmd, "count=%d, type=%s, memory=%s\n",
p->count, p->count,
prt_names(p->type,v4l2_type_names_FIXME), prt_names(p->type, v4l2_type_names),
prt_names(p->memory,v4l2_memory_names)); prt_names(p->memory, v4l2_memory_names));
break; break;
} }
case VIDIOC_QUERYBUF: case VIDIOC_QUERYBUF:
@ -858,7 +1192,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
enum v4l2_buf_type i = *(int *)arg; enum v4l2_buf_type i = *(int *)arg;
if (!vfd->vidioc_streamon) if (!vfd->vidioc_streamon)
break; break;
dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME)); dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret=vfd->vidioc_streamon(file, fh,i); ret=vfd->vidioc_streamon(file, fh,i);
break; break;
} }
@ -868,7 +1202,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
if (!vfd->vidioc_streamoff) if (!vfd->vidioc_streamoff)
break; break;
dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME)); dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret=vfd->vidioc_streamoff(file, fh, i); ret=vfd->vidioc_streamoff(file, fh, i);
break; break;
} }
@ -1624,7 +1958,7 @@ out:
kfree(mbuf); kfree(mbuf);
return err; return err;
} }
EXPORT_SYMBOL(video_ioctl2);
static const struct file_operations video_fops; static const struct file_operations video_fops;
@ -1743,6 +2077,7 @@ fail_minor:
mutex_unlock(&videodev_lock); mutex_unlock(&videodev_lock);
return ret; return ret;
} }
EXPORT_SYMBOL(video_register_device);
/** /**
* video_unregister_device - unregister a video4linux device * video_unregister_device - unregister a video4linux device
@ -1762,6 +2097,7 @@ void video_unregister_device(struct video_device *vfd)
device_unregister(&vfd->class_dev); device_unregister(&vfd->class_dev);
mutex_unlock(&videodev_lock); mutex_unlock(&videodev_lock);
} }
EXPORT_SYMBOL(video_unregister_device);
/* /*
* Video fs operations * Video fs operations
@ -1806,16 +2142,6 @@ static void __exit videodev_exit(void)
module_init(videodev_init) module_init(videodev_init)
module_exit(videodev_exit) module_exit(videodev_exit)
EXPORT_SYMBOL(video_register_device);
EXPORT_SYMBOL(video_unregister_device);
EXPORT_SYMBOL(video_devdata);
EXPORT_SYMBOL(video_usercopy);
EXPORT_SYMBOL(video_exclusive_open);
EXPORT_SYMBOL(video_exclusive_release);
EXPORT_SYMBOL(video_ioctl2);
EXPORT_SYMBOL(video_device_alloc);
EXPORT_SYMBOL(video_device_release);
MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>"); MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2"); MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -221,15 +221,15 @@ enum zoran_map_mode {
}; };
enum gpio_type { enum gpio_type {
GPIO_JPEG_SLEEP = 0, ZR_GPIO_JPEG_SLEEP = 0,
GPIO_JPEG_RESET, ZR_GPIO_JPEG_RESET,
GPIO_JPEG_FRAME, ZR_GPIO_JPEG_FRAME,
GPIO_VID_DIR, ZR_GPIO_VID_DIR,
GPIO_VID_EN, ZR_GPIO_VID_EN,
GPIO_VID_RESET, ZR_GPIO_VID_RESET,
GPIO_CLK_SEL1, ZR_GPIO_CLK_SEL1,
GPIO_CLK_SEL2, ZR_GPIO_CLK_SEL2,
GPIO_MAX, ZR_GPIO_MAX,
}; };
enum gpcs_type { enum gpcs_type {
@ -378,11 +378,11 @@ struct card_info {
u32 jpeg_int; /* JPEG interrupt */ u32 jpeg_int; /* JPEG interrupt */
u32 vsync_int; /* VSYNC interrupt */ u32 vsync_int; /* VSYNC interrupt */
s8 gpio[GPIO_MAX]; s8 gpio[ZR_GPIO_MAX];
u8 gpcs[GPCS_MAX]; u8 gpcs[GPCS_MAX];
struct vfe_polarity vfe_pol; struct vfe_polarity vfe_pol;
u8 gpio_pol[GPIO_MAX]; u8 gpio_pol[ZR_GPIO_MAX];
/* is the /GWS line conected? */ /* is the /GWS line conected? */
u8 gws_not_connected; u8 gws_not_connected;

View File

@ -250,7 +250,7 @@ void
jpeg_codec_sleep (struct zoran *zr, jpeg_codec_sleep (struct zoran *zr,
int sleep) int sleep)
{ {
GPIO(zr, zr->card.gpio[GPIO_JPEG_SLEEP], !sleep); GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_SLEEP], !sleep);
if (!sleep) { if (!sleep) {
dprintk(3, dprintk(3,
KERN_DEBUG KERN_DEBUG
@ -277,9 +277,9 @@ jpeg_codec_reset (struct zoran *zr)
0); 0);
udelay(2); udelay(2);
} else { } else {
GPIO(zr, zr->card.gpio[GPIO_JPEG_RESET], 0); GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 0);
udelay(2); udelay(2);
GPIO(zr, zr->card.gpio[GPIO_JPEG_RESET], 1); GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 1);
udelay(2); udelay(2);
} }
@ -688,7 +688,7 @@ static inline void
set_frame (struct zoran *zr, set_frame (struct zoran *zr,
int val) int val)
{ {
GPIO(zr, zr->card.gpio[GPIO_JPEG_FRAME], val); GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_FRAME], val);
} }
static void static void
@ -704,8 +704,8 @@ set_videobus_dir (struct zoran *zr,
GPIO(zr, 5, 1); GPIO(zr, 5, 1);
break; break;
default: default:
GPIO(zr, zr->card.gpio[GPIO_VID_DIR], GPIO(zr, zr->card.gpio[ZR_GPIO_VID_DIR],
zr->card.gpio_pol[GPIO_VID_DIR] ? !val : val); zr->card.gpio_pol[ZR_GPIO_VID_DIR] ? !val : val);
break; break;
} }
} }

View File

@ -93,6 +93,8 @@ static struct usb_device_id device_table[] = {
{USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 }, {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
{USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 }, {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
{USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 }, {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
{USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
{USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
{} /* Terminating entry */ {} /* Terminating entry */
}; };

View File

@ -12,6 +12,7 @@
#ifndef __LINUX_VIDEODEV_H #ifndef __LINUX_VIDEODEV_H
#define __LINUX_VIDEODEV_H #define __LINUX_VIDEODEV_H
#include <linux/ioctl.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__) #if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__)

View File

@ -62,6 +62,7 @@
#define __user #define __user
#include <sys/time.h> #include <sys/time.h>
#endif #endif
#include <linux/ioctl.h>
#include <linux/types.h> #include <linux/types.h>
/* /*

View File

@ -142,6 +142,7 @@ extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE];
#endif #endif

View File

@ -61,8 +61,6 @@
v4l_client_printk(KERN_DEBUG, client, fmt , ## arg); \ v4l_client_printk(KERN_DEBUG, client, fmt , ## arg); \
} while (0) } while (0)
/* Prints the ioctl in a human-readable format */
extern void v4l_printk_ioctl(unsigned int cmd);
/* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */ /* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */
#define v4l_print_ioctl(name, cmd) \ #define v4l_print_ioctl(name, cmd) \

View File

@ -44,6 +44,8 @@ extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
extern char *v4l2_norm_to_name(v4l2_std_id id); extern char *v4l2_norm_to_name(v4l2_std_id id);
extern int v4l2_video_std_construct(struct v4l2_standard *vs, extern int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, char *name); int id, char *name);
/* Prints the ioctl in a human-readable format */
extern void v4l_printk_ioctl(unsigned int cmd);
/* prority handling */ /* prority handling */
struct v4l2_prio_state { struct v4l2_prio_state {

View File

@ -149,7 +149,7 @@ struct videobuf_qtype_ops {
}; };
struct videobuf_queue { struct videobuf_queue {
struct mutex lock; struct mutex vb_lock;
spinlock_t *irqlock; spinlock_t *irqlock;
void *dev; /* on pci, points to struct pci_dev */ void *dev; /* on pci, points to struct pci_dev */

View File

@ -17,7 +17,7 @@
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
struct videbuf_vmalloc_memory struct videobuf_vmalloc_memory
{ {
u32 magic; u32 magic;