summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/drivers/media/dvb/dvb-usb/Kconfig3
-rw-r--r--linux/drivers/media/dvb/frontends/stv0299.c15
-rw-r--r--linux/drivers/media/dvb/frontends/tda10023.c20
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110.c1
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110.h1
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110_hw.c5
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110_hw.h3
-rw-r--r--linux/drivers/media/dvb/ttpci/budget-ci.c1
-rw-r--r--linux/drivers/media/video/cx18/cx18-cards.c43
-rw-r--r--linux/drivers/media/video/cx18/cx18-cards.h10
-rw-r--r--linux/drivers/media/video/cx18/cx18-dvb.c17
-rw-r--r--linux/drivers/media/video/cx18/cx18-gpio.c26
-rw-r--r--linux/drivers/media/video/cx18/cx18-gpio.h1
-rw-r--r--linux/drivers/media/video/cx18/cx18-i2c.c2
-rw-r--r--linux/drivers/media/video/videodev.c98
-rw-r--r--linux/include/media/v4l2-dev.h4
-rwxr-xr-xv4l/scripts/check_deps.pl228
17 files changed, 438 insertions, 40 deletions
diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig
index bee1bf3c9..7847a8320 100644
--- a/linux/drivers/media/dvb/dvb-usb/Kconfig
+++ b/linux/drivers/media/dvb/dvb-usb/Kconfig
@@ -76,6 +76,7 @@ config DVB_USB_DIB0700
select DVB_DIB3000MC
select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
select DVB_TUNER_DIB0070
help
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
@@ -107,6 +108,7 @@ config DVB_USB_CXUSB
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
help
Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode
@@ -121,6 +123,7 @@ config DVB_USB_M920X
select DVB_MT352 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
+ select DVB_TDA1004X if !DVB_FE_CUSTOMISE
help
Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
Currently, only devices with a product id of
diff --git a/linux/drivers/media/dvb/frontends/stv0299.c b/linux/drivers/media/dvb/frontends/stv0299.c
index 17556183e..35435bef8 100644
--- a/linux/drivers/media/dvb/frontends/stv0299.c
+++ b/linux/drivers/media/dvb/frontends/stv0299.c
@@ -63,6 +63,7 @@ struct stv0299_state {
u32 symbol_rate;
fe_code_rate_t fec_inner;
int errmode;
+ u32 ucblocks;
};
#define STATUS_BER 0
@@ -501,8 +502,10 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct stv0299_state* state = fe->demodulator_priv;
- if (state->errmode != STATUS_BER) return 0;
- *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+ if (state->errmode != STATUS_BER)
+ return -ENOSYS;
+
+ *ber = stv0299_readreg(state, 0x1e) | (stv0299_readreg(state, 0x1d) << 8);
return 0;
}
@@ -540,8 +543,12 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct stv0299_state* state = fe->demodulator_priv;
- if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0;
- else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+ if (state->errmode != STATUS_UCBLOCKS)
+ return -ENOSYS;
+
+ state->ucblocks += stv0299_readreg(state, 0x1e);
+ state->ucblocks += (stv0299_readreg(state, 0x1d) << 8);
+ *ucblocks = state->ucblocks;
return 0;
}
diff --git a/linux/drivers/media/dvb/frontends/tda10023.c b/linux/drivers/media/dvb/frontends/tda10023.c
index ec9d772c4..ccc63f064 100644
--- a/linux/drivers/media/dvb/frontends/tda10023.c
+++ b/linux/drivers/media/dvb/frontends/tda10023.c
@@ -74,9 +74,12 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
int ret;
ret = i2c_transfer (state->i2c, msg, 2);
- if (ret != 2)
- printk("DVB: TDA10023: %s: readreg error (ret == %i)\n",
- __func__, ret);
+ if (ret != 2) {
+ int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
+ printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error "
+ "(reg == 0x%02x, ret == %i)\n",
+ num, __func__, reg, ret);
+ }
return b1[0];
}
@@ -87,11 +90,12 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
int ret;
ret = i2c_transfer (state->i2c, &msg, 1);
- if (ret != 1)
- printk("DVB: TDA10023(%d): %s, writereg error "
+ if (ret != 1) {
+ int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
+ printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error "
"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- state->frontend.dvb->num, __func__, reg, data, ret);
-
+ num, __func__, reg, data, ret);
+ }
return (ret != 1) ? -EREMOTEIO : 0;
}
@@ -485,7 +489,7 @@ struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
struct tda10023_state* state = NULL;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct tda10023_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c
index 073ed350f..cc25b3380 100644
--- a/linux/drivers/media/dvb/ttpci/av7110.c
+++ b/linux/drivers/media/dvb/ttpci/av7110.c
@@ -1198,7 +1198,6 @@ static int start_ts_capture(struct av7110 *budget)
if (budget->feeding1)
return ++budget->feeding1;
memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
- budget->tsf = 0xff;
budget->ttbp = 0;
SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
diff --git a/linux/drivers/media/dvb/ttpci/av7110.h b/linux/drivers/media/dvb/ttpci/av7110.h
index 290ffc188..6cbf79c3e 100644
--- a/linux/drivers/media/dvb/ttpci/av7110.h
+++ b/linux/drivers/media/dvb/ttpci/av7110.h
@@ -200,7 +200,6 @@ struct av7110 {
struct dvb_net dvb_net1;
spinlock_t feedlock1;
int feeding1;
- u8 tsf;
u32 ttbp;
unsigned char *grabbing;
struct saa7146_pgtable pt;
diff --git a/linux/drivers/media/dvb/ttpci/av7110_hw.c b/linux/drivers/media/dvb/ttpci/av7110_hw.c
index ec049bb6e..afae0266a 100644
--- a/linux/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/linux/drivers/media/dvb/ttpci/av7110_hw.c
@@ -427,6 +427,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
if (err) {
printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
__func__, type);
+ av7110->arm_errors++;
return -ETIMEDOUT;
}
msleep(1);
@@ -853,10 +854,8 @@ static osd_raw_window_t bpp2bit[8] = {
static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
{
- int ret = wait_event_interruptible_timeout(av7110->bmpq,
+ int ret = wait_event_timeout(av7110->bmpq,
av7110->bmp_state != BMP_LOADING, 10*HZ);
- if (ret == -ERESTARTSYS)
- return ret;
if (ret == 0) {
printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
ret, av7110->bmp_state);
diff --git a/linux/drivers/media/dvb/ttpci/av7110_hw.h b/linux/drivers/media/dvb/ttpci/av7110_hw.h
index 74d940f75..ca99e5c1f 100644
--- a/linux/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/linux/drivers/media/dvb/ttpci/av7110_hw.h
@@ -305,7 +305,6 @@ enum av7110_command_type {
#define IRQ_STATE (DPRAM_BASE + 0x0F4)
#define IRQ_STATE_EXT (DPRAM_BASE + 0x0F6)
#define MSGSTATE (DPRAM_BASE + 0x0F8)
-#define FILT_STATE (DPRAM_BASE + 0x0FA)
#define COMMAND (DPRAM_BASE + 0x0FC)
#define COM_BUFF (DPRAM_BASE + 0x100)
#define COM_BUFF_SIZE 0x20
@@ -332,8 +331,6 @@ enum av7110_command_type {
/* firmware status area */
#define STATUS_BASE (DPRAM_BASE + 0x1FC0)
-#define STATUS_SCR (STATUS_BASE + 0x00)
-#define STATUS_MODES (STATUS_BASE + 0x04)
#define STATUS_LOOPS (STATUS_BASE + 0x08)
#define STATUS_MPEG_WIDTH (STATUS_BASE + 0x0C)
diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c
index 19ce91db9..c254ff242 100644
--- a/linux/drivers/media/dvb/ttpci/budget-ci.c
+++ b/linux/drivers/media/dvb/ttpci/budget-ci.c
@@ -237,6 +237,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
break;
case 0x1010:
case 0x1017:
+ case 0x101a:
/* for the Technotrend 1500 bundled remote */
ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_tt_1500);
diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c
index 45ad357ea..90857bedc 100644
--- a/linux/drivers/media/video/cx18/cx18-cards.c
+++ b/linux/drivers/media/video/cx18/cx18-cards.c
@@ -69,10 +69,10 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
{ CX18_CARD_INPUT_LINE_IN1,
CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
{ CX18_CARD_INPUT_LINE_IN2,
- CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
+ CX18_AV_AUDIO_SERIAL, CS5345_IN_3 },
},
.radio_input = { CX18_CARD_INPUT_AUD_TUNER,
- CX18_AV_AUDIO_SERIAL, 0 },
+ CX18_AV_AUDIO_SERIAL, CS5345_IN_4 },
.ddr = {
/* ESMT M13S128324A-5B memory */
.chip_config = 0x003,
@@ -84,6 +84,11 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
},
.gpio_init.initial_value = 0x3001,
.gpio_init.direction = 0x3001,
+ .gpio_i2c_slave_reset = {
+ .active_lo_mask = 0x3001,
+ .msecs_asserted = 10,
+ .msecs_recovery = 40,
+ },
.i2c = &cx18_i2c_std,
};
@@ -109,10 +114,10 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
{ CX18_CARD_INPUT_LINE_IN1,
CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
{ CX18_CARD_INPUT_LINE_IN2,
- CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
+ CX18_AV_AUDIO_SERIAL, CS5345_IN_3 },
},
.radio_input = { CX18_CARD_INPUT_AUD_TUNER,
- CX18_AV_AUDIO_SERIAL, 0 },
+ CX18_AV_AUDIO_SERIAL, CS5345_IN_4 },
.ddr = {
/* Samsung K4D263238G-VC33 memory */
.chip_config = 0x003,
@@ -124,6 +129,11 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
},
.gpio_init.initial_value = 0x3001,
.gpio_init.direction = 0x3001,
+ .gpio_i2c_slave_reset = {
+ .active_lo_mask = 0x3001,
+ .msecs_asserted = 10,
+ .msecs_recovery = 40,
+ },
.i2c = &cx18_i2c_std,
};
@@ -186,23 +196,26 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
static const struct cx18_card cx18_card_mpc718 = {
.type = CX18_CARD_YUAN_MPC718,
.name = "Yuan MPC718",
- .comment = "Not yet supported!\n",
- .v4l2_capabilities = 0,
+ .comment = "Some Composite and S-Video inputs are currently working.\n",
+ .v4l2_capabilities = CX18_CAP_ENCODER,
.hw_audio_ctrl = CX18_HW_CX23418,
.hw_all = CX18_HW_TUNER,
.video_inputs = {
- { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 },
- { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 },
- { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+ { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 },
+ { CX18_CARD_INPUT_SVIDEO1, 1,
+ CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+ { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+ { CX18_CARD_INPUT_SVIDEO2, 2,
+ CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+ { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+ { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 },
},
.audio_inputs = {
- { CX18_CARD_INPUT_AUD_TUNER,
- CX18_AV_AUDIO8, 0 },
- { CX18_CARD_INPUT_LINE_IN1,
- CX18_AV_AUDIO_SERIAL, 0 },
+ { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 },
+ { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL, 0 },
+ { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL, 0 },
},
- .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
- CX18_AV_AUDIO_SERIAL, 0 },
+ .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 0 },
.tuners = {
/* XC3028 tuner */
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
diff --git a/linux/drivers/media/video/cx18/cx18-cards.h b/linux/drivers/media/video/cx18/cx18-cards.h
index 47265d161..26ac41de2 100644
--- a/linux/drivers/media/video/cx18/cx18-cards.h
+++ b/linux/drivers/media/video/cx18/cx18-cards.h
@@ -78,6 +78,13 @@ struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
u32 initial_value;
};
+struct cx18_gpio_i2c_slave_reset {
+ u32 active_lo_mask; /* GPIO outputs that reset i2c chips when low */
+ u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */
+ int msecs_asserted; /* time period reset must remain asserted */
+ int msecs_recovery; /* time after deassert for chips to be ready */
+};
+
struct cx18_gpio_audio_input { /* select tuner/line in input */
u32 mask; /* leave to 0 if not supported */
u32 tuner;
@@ -121,7 +128,8 @@ struct cx18_card {
/* GPIO card-specific settings */
u8 xceive_pin; /* XCeive tuner GPIO reset pin */
- struct cx18_gpio_init gpio_init;
+ struct cx18_gpio_init gpio_init;
+ struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset;
struct cx18_gpio_audio_input gpio_audio_input;
struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c
index c9744173f..cae38985b 100644
--- a/linux/drivers/media/video/cx18/cx18-dvb.c
+++ b/linux/drivers/media/video/cx18/cx18-dvb.c
@@ -69,11 +69,21 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
struct dvb_demux *demux = feed->demux;
struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
struct cx18 *cx = stream->cx;
- int ret = -EINVAL;
+ int ret;
u32 v;
CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
feed->pid, feed->index);
+
+ mutex_lock(&cx->serialize_lock);
+ ret = cx18_init_on_first_open(cx);
+ mutex_unlock(&cx->serialize_lock);
+ if (ret) {
+ CX18_ERR("Failed to initialize firmware starting DVB feed\n");
+ return ret;
+ }
+ ret = -EINVAL;
+
switch (cx->card->type) {
case CX18_CARD_HVR_1600_ESMT:
case CX18_CARD_HVR_1600_SAMSUNG:
@@ -101,6 +111,11 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
if (stream->dvb.feeding++ == 0) {
CX18_DEBUG_INFO("Starting Transport DMA\n");
ret = cx18_start_v4l2_encode_stream(stream);
+ if (ret < 0) {
+ CX18_DEBUG_INFO(
+ "Failed to start Transport DMA\n");
+ stream->dvb.feeding--;
+ }
} else
ret = 0;
mutex_unlock(&stream->dvb.feedlock);
diff --git a/linux/drivers/media/video/cx18/cx18-gpio.c b/linux/drivers/media/video/cx18/cx18-gpio.c
index 6c0d9b5c6..089bad6d8 100644
--- a/linux/drivers/media/video/cx18/cx18-gpio.c
+++ b/linux/drivers/media/video/cx18/cx18-gpio.c
@@ -53,10 +53,34 @@ static void gpio_write(struct cx18 *cx)
write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
CX18_REG_GPIO_OUT1);
write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
- write_reg((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
+ write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
CX18_REG_GPIO_OUT2);
}
+void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
+{
+ const struct cx18_gpio_i2c_slave_reset *p;
+
+ p = &cx->card->gpio_i2c_slave_reset;
+
+ if ((p->active_lo_mask | p->active_hi_mask) == 0)
+ return;
+
+ /* Assuming that the masks are a subset of the bits in gpio_dir */
+
+ /* Assert */
+ cx->gpio_val =
+ (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
+ gpio_write(cx);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
+
+ /* Deassert */
+ cx->gpio_val =
+ (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
+ gpio_write(cx);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
+}
+
void cx18_gpio_init(struct cx18 *cx)
{
cx->gpio_dir = cx->card->gpio_init.direction;
diff --git a/linux/drivers/media/video/cx18/cx18-gpio.h b/linux/drivers/media/video/cx18/cx18-gpio.h
index 1e0168735..7447fed35 100644
--- a/linux/drivers/media/video/cx18/cx18-gpio.h
+++ b/linux/drivers/media/video/cx18/cx18-gpio.h
@@ -21,5 +21,6 @@
*/
void cx18_gpio_init(struct cx18 *cx);
+void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg);
diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c
index 7333f6001..5b8550e0e 100644
--- a/linux/drivers/media/video/cx18/cx18-i2c.c
+++ b/linux/drivers/media/video/cx18/cx18-i2c.c
@@ -453,6 +453,8 @@ int init_cx18_i2c(struct cx18 *cx)
cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
+ cx18_reset_i2c_slaves_gpio(cx);
+
return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
i2c_bit_add_bus(&cx->i2c_adap[1]);
}
diff --git a/linux/drivers/media/video/videodev.c b/linux/drivers/media/video/videodev.c
index aa75288ce..da78f4578 100644
--- a/linux/drivers/media/video/videodev.c
+++ b/linux/drivers/media/video/videodev.c
@@ -375,6 +375,14 @@ EXPORT_SYMBOL(v4l_printk_ioctl);
* sysfs stuff
*/
+static ssize_t show_index(struct device *cd,
+ struct device_attribute *attr, char *buf)
+{
+ struct video_device *vfd = container_of(cd, struct video_device,
+ class_dev);
+ return sprintf(buf, "%i\n", vfd->index);
+}
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
static ssize_t show_name(struct class_device *cd, char *buf)
#else
@@ -433,6 +441,7 @@ static void video_release(struct device *cd)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
static struct device_attribute video_device_attrs[] = {
__ATTR(name, S_IRUGO, show_name, NULL),
+ __ATTR(index, S_IRUGO, show_index, NULL),
__ATTR_NULL
};
#endif
@@ -1938,8 +1947,82 @@ out:
}
EXPORT_SYMBOL(video_ioctl2);
+struct index_info {
+ struct device *dev;
+ unsigned int used[VIDEO_NUM_DEVICES];
+};
+
+static int __fill_index_info(struct device *cd, void *data)
+{
+ struct index_info *info = data;
+ struct video_device *vfd = container_of(cd, struct video_device,
+ class_dev);
+
+ if (info->dev == vfd->dev)
+ info->used[vfd->index] = 1;
+
+ return 0;
+}
+
+/**
+ * assign_index - assign stream number based on parent device
+ * @vdev: video_device to assign index number to, vdev->dev should be assigned
+ * @num: -1 if auto assign, requested number otherwise
+ *
+ *
+ * returns -ENFILE if num is already in use, a free index number if
+ * successful.
+ */
+static int get_index(struct video_device *vdev, int num)
+{
+ struct index_info *info;
+ int i;
+ int ret = 0;
+
+ if (num >= VIDEO_NUM_DEVICES)
+ return -EINVAL;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = vdev->dev;
+
+ ret = class_for_each_device(&video_class, info,
+ __fill_index_info);
+
+ if (ret < 0)
+ goto out;
+
+ if (num >= 0) {
+ if (!info->used[num])
+ ret = num;
+ else
+ ret = -ENFILE;
+
+ goto out;
+ }
+
+ for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
+ if (info->used[i])
+ continue;
+ ret = i;
+ goto out;
+ }
+
+out:
+ kfree(info);
+ return ret;
+}
+
static const struct file_operations video_fops;
+int video_register_device(struct video_device *vfd, int type, int nr)
+{
+ return video_register_device_index(vfd, type, nr, -1);
+}
+EXPORT_SYMBOL(video_register_device);
+
/**
* video_register_device - register video4linux devices
* @vfd: video device structure we want to register
@@ -1965,7 +2048,8 @@ static const struct file_operations video_fops;
* %VFL_TYPE_RADIO - A radio card
*/
-int video_register_device(struct video_device *vfd, int type, int nr)
+int video_register_device_index(struct video_device *vfd, int type, int nr,
+ int index)
{
int i=0;
int base;
@@ -2022,6 +2106,16 @@ int video_register_device(struct video_device *vfd, int type, int nr)
}
video_device[i]=vfd;
vfd->minor=i;
+
+ ret = get_index(vfd, index);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: get_index failed\n",
+ __func__);
+ goto fail_minor;
+ }
+
+ vfd->index = ret;
+
mutex_unlock(&videodev_lock);
mutex_init(&vfd->lock);
@@ -2084,7 +2178,7 @@ fail_minor:
mutex_unlock(&videodev_lock);
return ret;
}
-EXPORT_SYMBOL(video_register_device);
+EXPORT_SYMBOL(video_register_device_index);
/**
* video_unregister_device - unregister a video4linux device
diff --git a/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h
index 0a03fa2f4..dff99a024 100644
--- a/linux/include/media/v4l2-dev.h
+++ b/linux/include/media/v4l2-dev.h
@@ -112,6 +112,8 @@ struct video_device
int type; /* v4l1 */
int type2; /* v4l2 */
int minor;
+ /* attribute to diferentiate multiple indexs on one physical device */
+ int index;
int debug; /* Activates debug level*/
@@ -377,6 +379,8 @@ void *priv;
/* Version 2 functions */
extern int video_register_device(struct video_device *vfd, int type, int nr);
+int video_register_device_index(struct video_device *vfd, int type, int nr,
+ int index);
void video_unregister_device(struct video_device *);
extern int video_ioctl2(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
diff --git a/v4l/scripts/check_deps.pl b/v4l/scripts/check_deps.pl
new file mode 100755
index 000000000..4071a9976
--- /dev/null
+++ b/v4l/scripts/check_deps.pl
@@ -0,0 +1,228 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+
+use strict;
+use File::Find;
+use Fcntl ':mode';
+use FileHandle;
+
+my $debug=0;
+
+my $SRC = 'linux';
+
+my %export;
+
+#############
+# open_makefile were adapted from analyze_build.pl
+# by Copyright (C) 2006 Trent Piepho <xyzzy@speakeasy.org>
+
+# Print out some extra checks of Makefile correctness
+my $check = 0;
+
+# Root of source tree
+my $root;
+
+# List of Makefile's opened
+my %makefiles = ();
+
+# For each module that is made up of multiple source files, list of sources
+my %multi = ();
+my $multi_count = 0;
+
+my %config;
+
+my %associate;
+
+sub open_makefile($) {
+ my $file = shift;
+
+ # only open a given Makefile once
+ return if exists $makefiles{$file};
+ $makefiles{$file} = 1;
+
+ $file =~ m|^(.*)/[^/]*$|;
+ my $dir = $1;
+
+ print "opening $root$file (dir=$dir)\n" if ($debug > 2);
+ my $in = new FileHandle;
+ open $in, '<', "$root$file" or die "Unable to open Makefile '$root$file': $!";
+
+ while (<$in>) {
+ # print STDERR "Line: $_";
+ # Skip comment and blank lines
+ next if (/^\s*(#.*)?$/);
+ m/^\s*\-?include/ and die "Can't handle includes! In $file";
+
+ # Handle line continuations
+ if (/\\\n$/) {
+ $_ .= <$in>;
+ redo;
+ }
+ # Eat line continuations in string we will parse
+ s/\s*\\\n\s*/ /g;
+ # Eat comments
+ s/#.*$//;
+
+ if (/^\s*obj-(\S+)\s*([:+]?)=\s*(\S.*?)\s*$/) {
+ print STDERR "Should use '+=' in $file:$.\n$_\n" if ($check && $2 ne '+');
+ my ($var,$targets) = ($1, $3);
+ if ($var =~ /\$\(CONFIG_(\S+)\)$/) {
+ $var = $1;
+ } elsif ($var !~ /^[ym]$/) {
+ print STDERR "Confused by obj assignment '$var' in $file:$.\n$_";
+ }
+ foreach(split(/\s+/, $targets)) {
+ if (m|/$|) { # Ends in /, means it's a directory
+ open_makefile("$dir/$_".'Makefile');
+ } elsif (/^(\S+)\.o$/) {
+ $config{"$dir/$1"} = $var;
+# printf "%s -> %s\n", $var, $1 if $debug > 1;
+ } else {
+ print STDERR "Confused by target '$_' in $file:$.\n";
+ }
+ }
+ next;
+ }
+ if (/(\S+)-objs\s*([:+]?)=\s*(\S.*?)\s*$/) {
+ my @files = split(/\s+/, $3);
+ map { s|^(.*)\.o$|$dir/\1| } @files;
+ if ($2 eq '+') {
+ # Adding to files
+ print STDERR "Should use ':=' in $file:$.\n$_\n" if ($check && !exists $multi{"$dir/$1"});
+ push @files, @{$multi{"$dir/$1"}};
+ } else {
+ print STDERR "Setting objects twice in $file:$.\n$_\n" if ($check && exists $multi{"$dir/$1"});
+ }
+ $multi{"$dir/$1"} = \@files;
+ next;
+ }
+ if (/^\s*EXTRA_CFLAGS\s*([:+]?)=\s*(\S.*?)\s*$/) {
+ if ($check) {
+ sub allI { /^-I/ or return 0 foreach split(/\s+/, $_[0]);return 1; }
+ my $use = allI($2) ? ':' : '+';
+ print STDERR "Should use '$use=' with EXTRA_CFLAGS in $file:$.\n$_\n"
+ if ($1 ne $use);
+ }
+ next;
+ }
+ print STDERR "Odd line $file:$.\n$_\n" if ($check);
+ }
+ close IN;
+}
+
+#
+#############
+
+sub associate_multi()
+{
+ foreach (keys %multi) {
+ my $name = $_;
+ my @files = @{$multi{$_}};
+ map { s/^(.*)$/\1.c/ } @files;
+
+ foreach (@files) {
+ my $file = $_;
+ my $var = $config{$name};
+ $associate{$file} = $var;
+ printf "$var -> $file\n" if $debug > 1;
+ }
+ delete $config{$name};
+ }
+ foreach my $file (keys %config) {
+ my $var = $config{$file};
+ $file .= ".c";
+ $associate{$file} = $var;
+ printf "$var -> $file\n" if $debug > 1;
+ }
+}
+
+sub build_exported_symbol_list {
+ my $file = $File::Find::name;
+
+ return if (!($file =~ /\.c$/));
+
+ open IN, $file;
+ while (<IN>) {
+ if (m/EXPORT_SYMBOL.*\(\s*([^\s\)]+)/) {
+ $export{$1} = $file;
+ printf "%s -> %s\n", $file , $1 if $debug > 1;
+ }
+ }
+ close IN;
+}
+
+
+sub find_usage_list {
+ my %depend;
+ my $file = $File::Find::name;
+ my $s;
+
+ return if (!($file =~ /\.c$/));
+
+ open IN, $file;
+ printf "Checking symbols at $file\n" if $debug;
+ while (<IN>) {
+ foreach my $symbol (keys %export) {
+ my $symb_file = $export{$symbol};
+
+ # Doesn't search the symbol at the file that defines it
+ next if ($symb_file eq $file);
+
+ if (m/($symbol)/) {
+ my $var = $associate{$symb_file};
+ if (!$depend{$var}) {
+ printf "$symbol found at $file. It depends on %s\n", $associate{$symb_file} if $debug;
+ $depend{$var} = 1;
+ }
+ }
+ }
+ }
+ close IN;
+
+ foreach (%depend) { $s .= "$_ && "; };
+ $s =~ s/\&\&\ $//;
+ if ($s ne "") {
+ print $associate{$file}." depends on $s\n";
+ }
+}
+
+print <<EOL;
+Dependency check tool for Kernel Symbols.
+
+Copyright(c) 2008 by Mauro Carvalho Chehab <mchehab\@infradead.org>
+This code is licenced under the terms of GPLv2.
+
+This script seeks all .c files under linux/ for their exported symbols. For
+each exported symbol, it will check what Kconfig symbol is associated. Then, it
+will cross-check that symbol usage and output a Kconfig depencency table.
+
+WARNING: The result of this tool should be used just as a hint, since, due to
+performance issues, and to simplify the tool, the checks will use a simple grep
+for the symbol string at the .c files, instead of a real symbol cross-check.
+
+Also, the same symbol may appear twice with different dependencies. This is due
+to the way it checks for symbols. The final dependency is the union (AND) of
+all showed ones for that symbol.
+
+Further patches improving this tool are welcome.
+
+EOL
+
+print "Checking makefile rules..." if $debug;
+open_makefile("$SRC/drivers/media/Makefile");
+print " ok\n" if $debug;
+
+print "Associating symbols with c files..." if $debug;
+associate_multi();
+print " ok\n" if $debug;
+
+print "finding exported symbols at $SRC..." if $debug;
+find({wanted => \&build_exported_symbol_list, no_chdir => 1}, $SRC);
+print " ok\n" if $debug;
+
+print "finding usage of symbols at $SRC\n" if $debug;
+find({wanted => \&find_usage_list, no_chdir => 1}, $SRC);
+print "finished\n" if $debug;
+