From a7dc2838bf1a5069828ca5a4f9e7a35916c95f7e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 28 Apr 2009 13:35:27 -0400 Subject: cx88: Fix race condition between cx8800 startup and hald From: Devin Heitmueller A power management fix to properly put the xc5000 into low power mode revealed a race condition where hald could detect the creation of the device file and connect to the device while the initial device configuration is still in progress. Lock the core structure so that video_release cannot be called and put the tuner to sleep in the middle of the initial call to cx88_set_tvnorm() in cx8800_initdev() Thanks to Michael Krufky for discovering the issue and providing an environment to test in. Priority: normal Signed-off-by: Devin Heitmueller Cc: Michael Krufky --- linux/drivers/media/video/cx88/cx88-video.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 88a326f61..2dfa4c9c3 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1152,8 +1152,10 @@ static int video_release(struct file *file) file->private_data = NULL; kfree(fh); + mutex_lock(&dev->core->lock); if(atomic_dec_and_test(&dev->core->users)) call_all(dev->core, tuner, s_standby); + mutex_unlock(&dev->core->lock); return 0; } -- cgit v1.2.3 From 3165ca2068855d7118d78396adce4c49a4e7f636 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 4 May 2009 20:43:02 -0400 Subject: dvb_frontend: fix race condition resulting in dropped tuning commands From: Devin Heitmueller A race condition was detected in the case that putting the tuner to sleep takes an unusually long period of time, combined with applications that quickly close/open the dvb frontend. The kaffeine channel scanner closes and reopens the dvb frontend between each tuning attempt. If it takes an unusually longer period of time to put the tuner to sleep (for example, the Pinnacle 801e takes 660 ms), the dvb_frontend thread will still be in a running state (and hence fepriv->thread is still set) but the fepriv->exit field will still be zero. As a result, if a dvb_frontend_start() call arrives while the frontend thread is in the process of terminating, the call will return 0 without actually starting a new thread. This results in the tuning request being dropped. To address this, mark fepriv->exit as soon as we know the thread is going to be terminated, so that dvb_frontend_start() knows to start a new instance. Problem encountered with Kaffeine 0.8.7 doing ATSC scanning against the Pinnacle 801e tuner, in conjunction with new code to power down the xc5000 when not in use. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index da2890b22..d359f6841 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -554,6 +554,7 @@ restart: if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { /* got signal or quitting */ + fepriv->exit = 1; break; } -- cgit v1.2.3 From 86afdeb7375f17f8ee3bbfcb3fcad5babf2ff002 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 15 Nov 2008 21:29:11 -0500 Subject: xc5000: handle tuner reset failures properly From: Devin Heitmueller Properly handle tuner reset failures (before it was always returning success) Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/common/tuners/xc5000.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index e38433ec6..9f7981b29 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -191,10 +191,10 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { {"FM Radio-INPUT1", 0x0208, 0x9002} }; -static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); -static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); -static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len); -static void xc5000_TunerReset(struct dvb_frontend *fe); +static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); +static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); +static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len); +static int xc5000_TunerReset(struct dvb_frontend *fe); static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) { @@ -208,18 +208,12 @@ static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) ? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS; } -static int xc_reset(struct dvb_frontend *fe) -{ - xc5000_TunerReset(fe); - return XC_RESULT_SUCCESS; -} - static void xc_wait(int wait_ms) { msleep(wait_ms); } -static void xc5000_TunerReset(struct dvb_frontend *fe) +static int xc5000_TunerReset(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; int ret; @@ -232,10 +226,15 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) priv->i2c_props.adap->algo_data, DVB_FRONTEND_COMPONENT_TUNER, XC5000_TUNER_RESET, 0); - if (ret) + if (ret) { printk(KERN_ERR "xc5000: reset failed\n"); - } else + return XC_RESULT_RESET_FAILURE; + } + } else { printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n"); + return XC_RESULT_RESET_FAILURE; + } + return XC_RESULT_SUCCESS; } static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) @@ -309,7 +308,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) len = i2c_sequence[index] * 256 + i2c_sequence[index+1]; if (len == 0x0000) { /* RESET command */ - result = xc_reset(fe); + result = xc5000_TunerReset(fe); index += 2; if (result != XC_RESULT_SUCCESS) return result; -- cgit v1.2.3 From dae6cf7668ce870a676f7770d4ff930566b8ea2c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Nov 2008 18:17:14 -0500 Subject: xc5000: cleanup i2c read routines From: Devin Heitmueller This patch centralizes the i2c read functions, and eliminates pass-through function only called by one caller. Make reading of xc5000 registers an atomic i2c transaction in case we're on a multi-master bus. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/common/tuners/xc5000.c | 62 ++++++++++-------------------- 1 file changed, 20 insertions(+), 42 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 9f7981b29..f199e2995 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -193,7 +193,7 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); -static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len); +static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); static int xc5000_TunerReset(struct dvb_frontend *fe); static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) @@ -202,10 +202,19 @@ static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) ? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS; } +/* This routine is never used because the only time we read data from the + i2c bus is when we read registers, and we want that to be an atomic i2c + transaction in case we are on a multi-master bus */ static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) { - return xc5000_readregs(priv, buf, len) - ? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS; + struct i2c_msg msg = { .addr = priv->i2c_props.addr, + .flags = I2C_M_RD, .buf = buf, .len = len }; + + if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { + printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", len); + return -EREMOTEIO; + } + return 0; } static void xc_wait(int wait_ms) @@ -275,25 +284,6 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) return result; } -static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData) -{ - u8 buf[2]; - int result; - - buf[0] = (regAddr >> 8) & 0xFF; - buf[1] = regAddr & 0xFF; - result = xc_send_i2c_data(priv, buf, 2); - if (result != XC_RESULT_SUCCESS) - return result; - - result = xc_read_i2c_data(priv, buf, 2); - if (result != XC_RESULT_SUCCESS) - return result; - - *i2cData = buf[0] * 256 + buf[1]; - return result; -} - static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) { struct xc5000_priv *priv = fe->tuner_priv; @@ -442,7 +432,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz) static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope) { - return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope); + return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope); } static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) @@ -451,7 +441,7 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) u16 regData; u32 tmp; - result = xc_read_reg(priv, XREG_FREQ_ERROR, ®Data); + result = xc5000_readreg(priv, XREG_FREQ_ERROR, ®Data); if (result) return result; @@ -462,7 +452,7 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status) { - return xc_read_reg(priv, XREG_LOCK, lock_status); + return xc5000_readreg(priv, XREG_LOCK, lock_status); } static int xc_get_version(struct xc5000_priv *priv, @@ -472,7 +462,7 @@ static int xc_get_version(struct xc5000_priv *priv, u16 data; int result; - result = xc_read_reg(priv, XREG_VERSION, &data); + result = xc5000_readreg(priv, XREG_VERSION, &data); if (result) return result; @@ -489,7 +479,7 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) u16 regData; int result; - result = xc_read_reg(priv, XREG_HSYNC_FREQ, ®Data); + result = xc5000_readreg(priv, XREG_HSYNC_FREQ, ®Data); if (result) return result; @@ -499,12 +489,12 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines) { - return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines); + return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines); } static int xc_get_quality(struct xc5000_priv *priv, u16 *quality) { - return xc_read_reg(priv, XREG_QUALITY, quality); + return xc5000_readreg(priv, XREG_QUALITY, quality); } static u16 WaitForLock(struct xc5000_priv *priv) @@ -554,7 +544,7 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) } *val = (bval[0] << 8) | bval[1]; - return 0; + return XC_RESULT_SUCCESS; } static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) @@ -570,18 +560,6 @@ static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) return 0; } -static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) -{ - struct i2c_msg msg = { .addr = priv->i2c_props.addr, - .flags = I2C_M_RD, .buf = buf, .len = len }; - - if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { - printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", (int)len); - return -EREMOTEIO; - } - return 0; -} - static int xc5000_fwupload(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; -- cgit v1.2.3 From 41e77d1f0a36b105066e184a540cbd98e4f7caf0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Nov 2008 18:20:06 -0500 Subject: xc5000: cleanup i2c write routines From: Devin Heitmueller Cleanup the i2c write routine, getting rid of a passthrough function with only one caller Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/common/tuners/xc5000.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index f199e2995..2945075d5 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -192,14 +192,19 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { }; static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); -static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); static int xc5000_TunerReset(struct dvb_frontend *fe); static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) { - return xc5000_writeregs(priv, buf, len) - ? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS; + struct i2c_msg msg = { .addr = priv->i2c_props.addr, + .flags = 0, .buf = buf, .len = len }; + + if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { + printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len); + return XC_RESULT_I2C_WRITE_FAILURE; + } + return XC_RESULT_SUCCESS; } /* This routine is never used because the only time we read data from the @@ -547,19 +552,6 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) return XC_RESULT_SUCCESS; } -static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) -{ - struct i2c_msg msg = { .addr = priv->i2c_props.addr, - .flags = 0, .buf = buf, .len = len }; - - if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { - printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", - (int)len); - return -EREMOTEIO; - } - return 0; -} - static int xc5000_fwupload(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; -- cgit v1.2.3 From 2615510561f94f4ed387ebad1dd5896e2a62ab60 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Nov 2008 18:23:19 -0500 Subject: xc5000: check xc5000_readreg return value for XC_RESULT_SUCCESS From: Devin Heitmueller Make return value checking for calls to i2c routines explicit. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/common/tuners/xc5000.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 2945075d5..0b2602d84 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -447,7 +447,7 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) u32 tmp; result = xc5000_readreg(priv, XREG_FREQ_ERROR, ®Data); - if (result) + if (result != XC_RESULT_SUCCESS) return result; tmp = (u32)regData; @@ -468,7 +468,7 @@ static int xc_get_version(struct xc5000_priv *priv, int result; result = xc5000_readreg(priv, XREG_VERSION, &data); - if (result) + if (result != XC_RESULT_SUCCESS) return result; (*hw_majorversion) = (data >> 12) & 0x0F; @@ -485,7 +485,7 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) int result; result = xc5000_readreg(priv, XREG_HSYNC_FREQ, ®Data); - if (result) + if (result != XC_RESULT_SUCCESS) return result; (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100; @@ -979,7 +979,7 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, /* Check if firmware has been loaded. It is possible that another instance of the driver has loaded the firmware. */ - if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) + if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS) goto fail; switch (id) { -- cgit v1.2.3 From 34741e4ed101a3989335c03aaaa0c0e7d20f3e94 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Nov 2008 18:41:07 -0500 Subject: xc5000: restore sleep routine From: Devin Heitmueller Bring back the code that puts the xc5000 to sleep. For the Pinnacle 801e this results in power consumption at idle dropping from 325ma to 124ma. If there are *actually* any devices that don't work in this configuration, they should set dvb_frontend.ops.tuner_ops.sleep to NULL (per mkrufky's suggestion) Also, had to make sure we were making sure the firmware was loaded in the digital version of set_params, or else we end up get i2c errors if the device is asleep Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/common/tuners/xc5000.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 0b2602d84..20e54014a 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -191,6 +191,7 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { {"FM Radio-INPUT1", 0x0208, 0x9002} }; +static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); static int xc5000_TunerReset(struct dvb_frontend *fe); @@ -365,15 +366,6 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, return ret; } -static int xc_shutdown(struct xc5000_priv *priv) -{ - return XC_RESULT_SUCCESS; - /* Fixme: cannot bring tuner back alive once shutdown - * without reloading the driver modules. - * return xc_write_reg(priv, XREG_POWER_DOWN, 0); - */ -} - static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) { dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, @@ -636,6 +628,9 @@ static int xc5000_set_params(struct dvb_frontend *fe, struct xc5000_priv *priv = fe->tuner_priv; int ret; + if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) + xc_load_fw_and_init_tuner(fe); + dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); switch (params->u.vsb.modulation) { @@ -713,8 +708,6 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe) return ret; } -static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); - static int xc5000_set_analog_params(struct dvb_frontend *fe, struct analog_parameters *params) { @@ -868,13 +861,7 @@ static int xc5000_sleep(struct dvb_frontend *fe) dprintk(1, "%s()\n", __func__); - /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized - * once shutdown without reloading the driver. Maybe I am not - * doing something right. - * - */ - - ret = xc_shutdown(priv); + ret = xc_write_reg(priv, XREG_POWER_DOWN, 0); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR "xc5000: %s() unable to shutdown tuner\n", -- cgit v1.2.3 From c48b2e1ef1551ce2b3985730c76b1aa97f653b1b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 16 Nov 2008 18:48:31 -0500 Subject: xc5000: do not sleep after digital tuning From: Devin Heitmueller Don't sleep for 400ms polling the tuner's lock if in digital mode (since the xc5000 lock status registers appear to only be reliable in analog mode) Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/common/tuners/xc5000.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 20e54014a..42836d695 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -509,7 +509,9 @@ static u16 WaitForLock(struct xc5000_priv *priv) return lockState; } -static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) +#define XC_TUNE_ANALOG 0 +#define XC_TUNE_DIGITAL 1 +static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode) { int found = 0; @@ -518,8 +520,10 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) return 0; - if (WaitForLock(priv) == 1) - found = 1; + if (mode == XC_TUNE_ANALOG) { + if (WaitForLock(priv) == 1) + found = 1; + } return found; } @@ -681,7 +685,7 @@ static int xc5000_set_params(struct dvb_frontend *fe, return -EIO; } - xc_tune_channel(priv, priv->freq_hz); + xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); if (debug) xc_debug_dump(priv); @@ -788,7 +792,7 @@ tune_channel: return -EREMOTEIO; } - xc_tune_channel(priv, priv->freq_hz); + xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); if (debug) xc_debug_dump(priv); -- cgit v1.2.3 From 02073646971a4917cfe3ff0ccb4a85fd126dab6e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 2 Apr 2009 20:50:11 -0400 Subject: xc5000: switch to new version of Xceive firmware From: Devin Heitmueller This switches to a new version of the xc5000 firmware, extracted from the latest Hauppauge driver. It includes the support for the XREG_BUSY register (a lack of which was causing tuning to take 3200ms instead of around 300ms). Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 42836d695..8583689f9 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -42,8 +42,8 @@ static LIST_HEAD(hybrid_tuner_instance_list); #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) -#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" -#define XC5000_DEFAULT_FIRMWARE_SIZE 12332 +#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.4.68.fw" +#define XC5000_DEFAULT_FIRMWARE_SIZE 12378 struct xc5000_priv { struct tuner_i2c_props i2c_props; -- cgit v1.2.3 From 8045b10212368c3a790397140241fedb87693641 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 2 Apr 2009 21:02:39 -0400 Subject: xc5000: Properly support power down for newer firmware From: Devin Heitmueller Xceive got rid of the XREG_POWER_DOWN register in later firmware revisions. Their technical support informed me that the correct way to put the tuner to sleep is to pull the reset pin (but don't reload the firmware). Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 8583689f9..2ca2cba6d 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -83,7 +83,7 @@ struct xc5000_priv { #define XREG_D_CODE 0x04 #define XREG_IF_OUT 0x05 #define XREG_SEEK_MODE 0x07 -#define XREG_POWER_DOWN 0x0A +#define XREG_POWER_DOWN 0x0A /* Obsolete */ #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */ #define XREG_SMOOTHEDCVBS 0x0E #define XREG_XTALFREQ 0x0F @@ -860,12 +860,14 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) static int xc5000_sleep(struct dvb_frontend *fe) { - struct xc5000_priv *priv = fe->tuner_priv; int ret; dprintk(1, "%s()\n", __func__); - ret = xc_write_reg(priv, XREG_POWER_DOWN, 0); + /* According to Xceive technical support, the "powerdown" register + was removed in newer versions of the firmware. The "supported" + way to sleep the tuner is to pull the reset pin low for 10ms */ + ret = xc5000_TunerReset(fe); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR "xc5000: %s() unable to shutdown tuner\n", -- cgit v1.2.3 From 88c300ff3c421a23a0c8e72a0c768f58e74f9221 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 2 Apr 2009 21:14:51 -0400 Subject: au0828: reduce reset time for xc5000 to 10ms From: Devin Heitmueller The xc5000 datasheet indicates that the reset pin only needs to be held low for 10ms. Reduce the value accordingly, which speeds up the firmware load time a bit. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-cards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-cards.c b/linux/drivers/media/video/au0828/au0828-cards.c index 053bbe8c8..830c4a933 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -136,9 +136,9 @@ int au0828_tuner_callback(void *priv, int component, int command, int arg) /* Tuner Reset Command from xc5000 */ /* Drive the tuner into reset and out */ au0828_clear(dev, REG_001, 2); - mdelay(200); + mdelay(10); au0828_set(dev, REG_001, 2); - mdelay(50); + mdelay(10); return 0; } else { printk(KERN_ERR -- cgit v1.2.3 From 56b45a9ffa2227538376556bb0536b1ef932ab33 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 2 Apr 2009 21:24:38 -0400 Subject: xc5000: add build version to debug info From: Devin Heitmueller Expose the firmware build number along with the other version info Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 2ca2cba6d..e35d4d888 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -100,6 +100,7 @@ struct xc5000_priv { #define XREG_VERSION 0x07 #define XREG_PRODUCT_ID 0x08 #define XREG_BUSY 0x09 +#define XREG_BUILD 0x0D /* Basic firmware description. This will remain with @@ -471,6 +472,11 @@ static int xc_get_version(struct xc5000_priv *priv, return 0; } +static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev) +{ + return xc5000_readreg(priv, XREG_BUILD, buildrev); +} + static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) { u16 regData; @@ -593,6 +599,7 @@ static void xc_debug_dump(struct xc5000_priv *priv) u16 quality; u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; + u16 fw_buildversion = 0; /* Wait for stats to stabilize. * Frame Lines needs two frame times after initial lock @@ -612,9 +619,10 @@ static void xc_debug_dump(struct xc5000_priv *priv) xc_get_version(priv, &hw_majorversion, &hw_minorversion, &fw_majorversion, &fw_minorversion); - dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n", + xc_get_buildversion(priv, &fw_buildversion); + dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n", hw_majorversion, hw_minorversion, - fw_majorversion, fw_minorversion); + fw_majorversion, fw_minorversion, fw_buildversion); xc_get_hsync_freq(priv, &hsync_freq_hz); dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz); -- cgit v1.2.3 From 327592abb68b0a7f1598ea2e5ffbc770cf1411f5 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 2 Apr 2009 21:40:29 -0400 Subject: xc5000: start using the newer "finerfreq" tuning command From: Devin Heitmueller Starting in firmware version 1.1.44, Xceive recommends using the FINERFREQ for all normal tuning (the doc indicates reg 0x03 should only be used for fast scanning for channel lock) Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index e35d4d888..d90bcbe78 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -87,7 +87,7 @@ struct xc5000_priv { #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */ #define XREG_SMOOTHEDCVBS 0x0E #define XREG_XTALFREQ 0x0F -#define XREG_FINERFFREQ 0x10 +#define XREG_FINERFREQ 0x10 #define XREG_DDIMODE 0x11 #define XREG_ADC_ENV 0x00 @@ -395,22 +395,14 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) freq_code = (u16)(freq_hz / 15625); - return xc_write_reg(priv, XREG_RF_FREQ, freq_code); + /* Starting in firmware version 1.1.44, Xceive recommends using the + FINERFREQ for all normal tuning (the doc indicates reg 0x03 should + only be used for fast scanning for channel lock) */ + return xc_write_reg(priv, XREG_FINERFREQ, freq_code); } #if 0 /* We'll probably need these for analog support */ -static int xc_FineTune_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) -{ - u16 freq_code = (u16)(freq_hz / 15625); - - if ((freq_hz > xc5000_tuner_ops.info.frequency_max) || - (freq_hz < xc5000_tuner_ops.info.frequency_min)) - return XC_RESULT_OUT_OF_RANGE; - - return xc_write_reg(priv, XREG_FINERFFREQ, freq_code); -} - static int xc_set_Xtal_frequency(struct xc5000_priv *priv, u32 xtalFreqInKHz) { u16 xtalRatio = (32000 * 0x8000)/xtalFreqInKHz; -- cgit v1.2.3 From 72c6b08f362a4159baccf0956151cf54f0f25e2e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 2 Apr 2009 21:45:17 -0400 Subject: xc5000: cleanup firmware loading messages From: Devin Heitmueller Make it a little more obvious in the dmesg output what is going on during firmware upload. This is more important for boards like the HVR-950q that take nearly seven seconds to do the upload. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index d90bcbe78..4045b2d50 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -563,7 +563,7 @@ static int xc5000_fwupload(struct dvb_frontend *fe) ret = XC_RESULT_RESET_FAILURE; goto out; } else { - printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n", + printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n", fw->size); ret = XC_RESULT_SUCCESS; } @@ -572,8 +572,9 @@ static int xc5000_fwupload(struct dvb_frontend *fe) printk(KERN_ERR "xc5000: firmware incorrect size\n"); ret = XC_RESULT_RESET_FAILURE; } else { - printk(KERN_INFO "xc5000: firmware upload\n"); + printk(KERN_INFO "xc5000: firmware uploading...\n"); ret = xc_load_i2c_sequence(fe, fw->data); + printk(KERN_INFO "xc5000: firmware upload complete...\n"); } out: -- cgit v1.2.3 From 413a852cd71a91beba74baab6cd04d6303aed136 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 28 Apr 2009 12:53:38 -0400 Subject: xc5000: add "no_poweroff" module option From: Devin Heitmueller Provide for the ability for a user to disable putting the tuner to sleep, in case he doesn't want to incur the cost of reloading the firmware when starting up his/her application. The module options are intentionally identical to xc3028. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 4045b2d50..f2a034b51 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -36,6 +36,12 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +static int no_poweroff; +module_param(no_poweroff, int, 0644); +MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n" + "\t\t1 keep device energized and with tuner ready all the times.\n" + "\t\tFaster, but consumes more power and keeps the device hotter"); + static DEFINE_MUTEX(xc5000_list_mutex); static LIST_HEAD(hybrid_tuner_instance_list); @@ -865,6 +871,10 @@ static int xc5000_sleep(struct dvb_frontend *fe) dprintk(1, "%s()\n", __func__); + /* Avoid firmware reload on slow devices */ + if (no_poweroff) + return 0; + /* According to Xceive technical support, the "powerdown" register was removed in newer versions of the firmware. The "supported" way to sleep the tuner is to pull the reset pin low for 10ms */ -- cgit v1.2.3 From 6ef6553900dddf6ab737699fbae806b1cf03486a Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 28 Apr 2009 13:07:14 -0400 Subject: xc5000: don't load firmware until a tuning request is made From: Devin Heitmueller Defer loading of the xc5000 firmware until it is actually needed. This helps on distros that have hald, which results in the device not being available for use for around ten seconds in cases where the i2c bus is slow (such as the HVR-950Q). Also, the firmware load isn't really useful since we immediately put the device to sleep afterward, which means a firmware reload will be required anyway. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/tuner-core.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index bb60c910e..cb715f143 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -434,10 +434,6 @@ static void set_type(struct i2c_client *c, unsigned int type, if (!dvb_attach(xc5000_attach, &t->fe, t->i2c->adapter, &xc5000_cfg)) goto attach_failed; - - xc_tuner_ops = &t->fe.ops.tuner_ops; - if (xc_tuner_ops->init) - xc_tuner_ops->init(&t->fe); break; } default: -- cgit v1.2.3 From ed2d96e96805f671a8919bc8a4204f0e7e55238c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 28 Apr 2009 15:22:47 -0400 Subject: tuner-xc2028: show the proper module description for no_poweroff option From: Devin Heitmueller There was a typo in the module description for the "no_poweroff" option, where the help was being associated with the "debug" option instead. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/tuner-xc2028.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c index 3f03dfa2c..cb5b577fa 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -34,7 +34,7 @@ MODULE_PARM_DESC(debug, "enable verbose debug messages"); static int no_poweroff; module_param(no_poweroff, int, 0644); -MODULE_PARM_DESC(debug, "0 (default) powers device off when not used.\n" +MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n" "1 keep device energized and with tuner ready all the times.\n" " Faster, but consumes more power and keeps the device hotter\n"); -- cgit v1.2.3 From 8daa6a71db80a0910916ffe840d4c9dc520e1310 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 4 May 2009 20:57:41 -0400 Subject: dib0700: reduce xc5000 sleep time for Pinnacle 801e to 10ms From: Devin Heitmueller According to the xc5000 spec, the reset pin only needs to be held low for 10ms. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index e39993df0..ac97b9f42 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1346,9 +1346,9 @@ static int dib0700_xc5000_tuner_callback(void *priv, int component, if (command == XC5000_TUNER_RESET) { /* Reset the tuner */ dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); - msleep(330); /* from Windows USB trace */ + msleep(10); dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); - msleep(330); /* from Windows USB trace */ + msleep(10); } else { err("xc5000: unknown tuner callback command: %d\n", command); return -EINVAL; -- cgit v1.2.3 From 68a68df1c6030e5e259627d4e99b422a4059f5fc Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 4 May 2009 21:04:20 -0400 Subject: xc5000: switch to new xc5000 firmware 1.6.114 with redistribution rights From: Devin Heitmueller Xceive has graciously allowed us to now freely redistribute the xc5000 firmware, which eliminates the need for users to manually extract the blob from the Hauppauge driver. Thanks to Brian Mathews for providing this code Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index f2a034b51..f7358bc6e 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -48,8 +48,8 @@ static LIST_HEAD(hybrid_tuner_instance_list); #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) -#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.4.68.fw" -#define XC5000_DEFAULT_FIRMWARE_SIZE 12378 +#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" +#define XC5000_DEFAULT_FIRMWARE_SIZE 12401 struct xc5000_priv { struct tuner_i2c_props i2c_props; -- cgit v1.2.3 From 4cca9aa01782049817d8d9abf78e683e3c7dfd0e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 4 May 2009 21:59:58 -0400 Subject: xc5000: add support for DVB-T tuning From: David T.L. Wong This patch adds XC5000 supports for DVB-T 6MHz and 8MHz bandwidth. Priority: normal Signed-off-by: David T.L. Wong Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 63 +++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index f7358bc6e..8428e341a 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -644,25 +644,52 @@ static int xc5000_set_params(struct dvb_frontend *fe, dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); - switch (params->u.vsb.modulation) { - case VSB_8: - case VSB_16: - dprintk(1, "%s() VSB modulation\n", __func__); + if (fe->ops.info.type == FE_ATSC) { + dprintk(1, "%s() ATSC\n", __func__); + switch (params->u.vsb.modulation) { + case VSB_8: + case VSB_16: + dprintk(1, "%s() VSB modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_AIR; + priv->freq_hz = params->frequency - 1750000; + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + break; + case QAM_64: + case QAM_256: + case QAM_AUTO: + dprintk(1, "%s() QAM modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_CABLE; + priv->freq_hz = params->frequency - 1750000; + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + break; + default: + return -EINVAL; + } + } else if (fe->ops.info.type == FE_OFDM) { + dprintk(1, "%s() OFDM\n", __func__); + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + priv->freq_hz = params->frequency - 1750000; + break; + case BANDWIDTH_7_MHZ: + printk(KERN_ERR "xc5000 bandwidth 7MHz not supported\n"); + return -EINVAL; + case BANDWIDTH_8_MHZ: + priv->bandwidth = BANDWIDTH_8_MHZ; + priv->video_standard = DTV8; + priv->freq_hz = params->frequency - 2750000; + break; + default: + printk(KERN_ERR "xc5000 bandwidth not set!\n"); + return -EINVAL; + } priv->rf_mode = XC_RF_MODE_AIR; - priv->freq_hz = params->frequency - 1750000; - priv->bandwidth = BANDWIDTH_6_MHZ; - priv->video_standard = DTV6; - break; - case QAM_64: - case QAM_256: - case QAM_AUTO: - dprintk(1, "%s() QAM modulation\n", __func__); - priv->rf_mode = XC_RF_MODE_CABLE; - priv->freq_hz = params->frequency - 1750000; - priv->bandwidth = BANDWIDTH_6_MHZ; - priv->video_standard = DTV6; - break; - default: + } else { + printk(KERN_ERR "xc5000 modulation type not supported!\n"); return -EINVAL; } -- cgit v1.2.3 From c69585fadf77969b8eb7eee245fcb38f300227dd Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 4 May 2009 22:29:17 -0400 Subject: xc5000: poll at 5ms interval for register write command completion From: Devin Heitmueller Instead of polling at 100ms intervals for register writes, poll at 5ms intervals. This is consistent with the xc5000 specification, and improves tuning time by up to 500 ms on devices that such as the au0828 which do not properly implement i2c clock stretching (since the five register writes that occur for a tuning request often do not complete immediately but do complete far before 100ms has gone by). The net amount of time we wait before timing out is unchanged (500ms). Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/xc5000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 8428e341a..c8c586b64 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -262,7 +262,7 @@ static int xc5000_TunerReset(struct dvb_frontend *fe) static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) { u8 buf[4]; - int WatchDogTimer = 5; + int WatchDogTimer = 100; int result; buf[0] = (regAddr >> 8) & 0xFF; @@ -284,7 +284,7 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) /* busy flag cleared */ break; } else { - xc_wait(100); /* wait 5 ms */ + xc_wait(5); /* wait 5 ms */ WatchDogTimer--; } } -- cgit v1.2.3 From 56094f2f714025a756faf2acd42500698dacb100 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 6 May 2009 17:30:30 +0200 Subject: uvcvideo: Parse frame descriptors with non-continuous indexes. From: Laurent Pinchart The UVC specification requires frame descriptors indexes to range from 1 to the number of frame descriptors. At least some Hercules Dualpix Infinite webcams erroneously use non-continuous index ranges. Make the driver support them. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 24 ++---------------------- linux/drivers/media/video/uvc/uvc_video.c | 17 +++++++++++------ 2 files changed, 13 insertions(+), 28 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 31d60647d..94bb63ef1 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -289,10 +289,8 @@ static int uvc_parse_format(struct uvc_device *dev, struct uvc_format_desc *fmtdesc; struct uvc_frame *frame; const unsigned char *start = buffer; - unsigned char *_buffer; unsigned int interval; unsigned int i, n; - int _buflen; __u8 ftype; format->type = buffer[2]; @@ -413,20 +411,11 @@ static int uvc_parse_format(struct uvc_device *dev, buflen -= buffer[0]; buffer += buffer[0]; - /* Count the number of frame descriptors to test the bFrameIndex - * field when parsing the descriptors. We can't rely on the - * bNumFrameDescriptors field as some cameras don't initialize it - * properly. - */ - for (_buflen = buflen, _buffer = buffer; - _buflen > 2 && _buffer[2] == ftype; - _buflen -= _buffer[0], _buffer += _buffer[0]) - format->nframes++; - /* Parse the frame descriptors. Only uncompressed, MJPEG and frame * based formats have frame descriptors. */ while (buflen > 2 && buffer[2] == ftype) { + frame = &format->frame[format->nframes]; if (ftype != VS_FRAME_FRAME_BASED) n = buflen > 25 ? buffer[25] : 0; else @@ -441,16 +430,6 @@ static int uvc_parse_format(struct uvc_device *dev, return -EINVAL; } - if (buffer[3] - 1 >= format->nframes) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" - "interface %d frame index %u out of range\n", - dev->udev->devnum, alts->desc.bInterfaceNumber, - buffer[3]); - return -EINVAL; - } - - frame = &format->frame[buffer[3] - 1]; - frame->bFrameIndex = buffer[3]; frame->bmCapabilities = buffer[4]; frame->wWidth = get_unaligned_le16(&buffer[5]); @@ -507,6 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev, 10000000/frame->dwDefaultFrameInterval, (100000000/frame->dwDefaultFrameInterval)%10); + format->nframes++; buflen -= buffer[0]; buffer += buffer[0]; } diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index c5df33de9..07e755ba7 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -65,7 +65,8 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, struct uvc_streaming_control *ctrl) { struct uvc_format *format; - struct uvc_frame *frame; + struct uvc_frame *frame = NULL; + unsigned int i; if (ctrl->bFormatIndex <= 0 || ctrl->bFormatIndex > video->streaming->nformats) @@ -73,11 +74,15 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, format = &video->streaming->format[ctrl->bFormatIndex - 1]; - if (ctrl->bFrameIndex <= 0 || - ctrl->bFrameIndex > format->nframes) - return; + for (i = 0; i < format->nframes; ++i) { + if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { + frame = &format->frame[i]; + break; + } + } - frame = &format->frame[ctrl->bFrameIndex - 1]; + if (frame == NULL) + return; if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || (ctrl->dwMaxVideoFrameSize == 0 && @@ -1093,7 +1098,7 @@ int uvc_video_init(struct uvc_video_device *video) /* Zero bFrameIndex might be correct. Stream-based formats (including * MPEG-2 TS and DV) do not support frames but have a dummy frame * descriptor with bFrameIndex set to zero. If the default frame - * descriptor is not found, use the first avalable frame. + * descriptor is not found, use the first available frame. */ for (i = format->nframes; i > 0; --i) { frame = &format->frame[i-1]; -- cgit v1.2.3 From b872a134312bd4a2a97b537ab0b547a021d594df Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 6 May 2009 17:37:44 +0200 Subject: uvcvideo: Add missing whitespaces to multi-line format strings. From: Laurent Pinchart Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 94bb63ef1..1768389c4 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -301,7 +301,7 @@ static int uvc_parse_format(struct uvc_device *dev, case VS_FORMAT_FRAME_BASED: n = buffer[2] == VS_FORMAT_UNCOMPRESSED ? 27 : 28; if (buflen < n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); @@ -336,7 +336,7 @@ static int uvc_parse_format(struct uvc_device *dev, case VS_FORMAT_MJPEG: if (buflen < 11) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); @@ -352,7 +352,7 @@ static int uvc_parse_format(struct uvc_device *dev, case VS_FORMAT_DV: if (buflen < 9) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); @@ -370,7 +370,7 @@ static int uvc_parse_format(struct uvc_device *dev, strlcpy(format->name, "HD-DV", sizeof format->name); break; default: - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d: unknown DV format %u\n", dev->udev->devnum, alts->desc.bInterfaceNumber, buffer[8]); @@ -399,7 +399,7 @@ static int uvc_parse_format(struct uvc_device *dev, case VS_FORMAT_STREAM_BASED: /* Not supported yet. */ default: - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d unsupported format %u\n", dev->udev->devnum, alts->desc.bInterfaceNumber, buffer[2]); @@ -424,7 +424,7 @@ static int uvc_parse_format(struct uvc_device *dev, n = n ? n : 3; if (buflen < 26 + 4*n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FRAME error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); return -EINVAL; @@ -498,7 +498,7 @@ static int uvc_parse_format(struct uvc_device *dev, if (buflen > 2 && buffer[2] == VS_COLORFORMAT) { if (buflen < 6) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d COLORFORMAT error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); @@ -1296,7 +1296,7 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video, continue; if (forward->extension.bNrInPins != 1) { - uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has" + uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has " "more than 1 input pin.\n", entity->id); return -1; } -- cgit v1.2.3 From a46ec326b79a229fdb0205fa793525ba8d234907 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 6 May 2009 19:54:00 -0400 Subject: au0828: send command to power down tuner when done with analog From: Devin Heitmueller Make sure the au0828 issues the command to power down the tuner when the user is done using analog support. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-video.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index 8bc0f0481..f73212415 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -834,6 +834,9 @@ static int au0828_v4l2_close(struct file *filp) au0828_uninit_isoc(dev); + /* Save some power by putting tuner to sleep */ + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); + /* When close the device, set the usb intf0 into alt0 to free USB bandwidth */ ret = usb_set_interface(dev->usbdev, 0, 0); -- cgit v1.2.3 From d6b15c1777cb188ed9f4916ec7b6cde43dbd2926 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 14 May 2009 20:31:11 -0400 Subject: xc5000: add copyright line From: Devin Heitmueller Add copyright line for xc5000.c. Priority: normal Signed-off-by: Devin Heitmueller Cc: Steven Toth --- linux/drivers/media/common/tuners/xc5000.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index c8c586b64..6626d19b3 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -3,6 +3,7 @@ * * Copyright (c) 2007 Xceive Corporation * Copyright (c) 2007 Steven Toth + * Copyright (c) 2009 Devin Heitmueller * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From a3f229ca91e3b8f799c2799ab2cf3398fff6bcaf Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 14 May 2009 20:50:36 -0400 Subject: cx88: remove xc5000 reset for Pinnacle 800i From: Devin Heitmueller According to the engineer at PCTV Systems, the xc5000 reset pin is supposed to be on GPIO12. However, despite three nights of effort, pulling that GPIO low didn't reset the xc5000. While pulling MO_SRST_IO low does reset the xc5000, this also resets in the s5h1409 being reset as well. This causes tuning to always fail since the internal state of the s5h1409 does not match the driver's state. Given that the only two conditions in which the driver performs a reset is during firmware load and powering down the chip, I am taking out the reset. We know that the chip is being reset when the cx88 comes online, and not being able to do power management for this board is better than not having any tuning at all. Problem discovered when implementing proper power management for the xc5000, which results in calls to the reset callback *after* s5h1409 is initialized. Priority: normal Signed-off-by: Devin Heitmueller Cc: Steven Toth Cc: Chaogui Zhang --- linux/drivers/media/video/cx88/cx88-cards.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index c9bfa835e..546793c02 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -2735,10 +2735,22 @@ static int cx88_xc5000_tuner_callback(struct cx88_core *core, switch (core->boardnr) { case CX88_BOARD_PINNACLE_PCTV_HD_800i: if (command == 0) { /* This is the reset command from xc5000 */ - /* Reset XC5000 tuner via SYS_RSTO_pin */ - cx_write(MO_SRST_IO, 0); - msleep(10); - cx_write(MO_SRST_IO, 1); + + /* djh - According to the engineer at PCTV Systems, + the xc5000 reset pin is supposed to be on GPIO12. + However, despite three nights of effort, pulling + that GPIO low didn't reset the xc5000. While + pulling MO_SRST_IO low does reset the xc5000, this + also resets in the s5h1409 being reset as well. + This causes tuning to always fail since the internal + state of the s5h1409 does not match the driver's + state. Given that the only two conditions in which + the driver performs a reset is during firmware load + and powering down the chip, I am taking out the + reset. We know that the chip is being reset + when the cx88 comes online, and not being able to + do power management for this board is worse than + not having any tuning at all. */ return 0; } else { err_printk(core, "xc5000: unknown tuner " -- cgit v1.2.3 From d0db8610838988ce38aff9812c90d8623097e0f5 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 14 May 2009 22:38:51 -0400 Subject: au0828: get rid of debug printk that was causing compile failures From: Devin Heitmueller Remove a debug printk() line I added which is no longer needed, and happened to be causing compile failures on some earlier kernels in Han's daily compile report. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-video.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index 8bc0f0481..a2414818c 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -915,11 +915,6 @@ static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - dprintk(2, "vma start=0x%08lx, size=%ld, ret=%d\n", - (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, - rc); - return rc; } -- cgit v1.2.3 From 0144095d5249bc72fdc5930fa52de0fc29a5ac6f Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 16 May 2009 16:09:28 -0400 Subject: em28xx: properly set packet size based on the device's eeprom configuration. From: Devin Heitmueller The em28xx actually has a register that tells the driver what the maximum packet size is (based on a value programmed into the eeprom). Make use of that register instead of assuming a hardcoded value of 564 (since 564 is not correct for devices that do QAM such as the KWorld 340u). Note that for now the em2874 code isn't there, falling back to the 564 value, however this is not a problem since there are not any em2874 based devices in the current v4l-dvb tree). Thanks to Jarod Wilson for detecting the initial problem and figuring out that the isoc configuration was wrong for his device. Priority: normal Signed-off-by: Devin Heitmueller Cc: Jarod Wilson --- linux/drivers/media/video/em28xx/em28xx-core.c | 35 ++++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-dvb.c | 6 +++-- linux/drivers/media/video/em28xx/em28xx-reg.h | 16 ++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 4 files changed, 56 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 401dc4e39..02e51af9d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -1021,6 +1021,41 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, } EXPORT_SYMBOL_GPL(em28xx_init_isoc); +/* Determine the packet size for the DVB stream for the given device + (underlying value programmed into the eeprom) */ +int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev) +{ + unsigned int chip_cfg2; + unsigned int packet_size = 564; + + if (dev->chip_id == CHIP_ID_EM2874) { + /* FIXME - for now assume 564 like it was before, but the + em2874 code should be added to return the proper value... */ + packet_size = 564; + } else { + /* TS max packet size stored in bits 1-0 of R01 */ + chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2); + switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) { + case EM28XX_CHIPCFG2_TS_PACKETSIZE_188: + packet_size = 188; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_376: + packet_size = 376; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_564: + packet_size = 564; + break; + case EM28XX_CHIPCFG2_TS_PACKETSIZE_752: + packet_size = 752; + break; + } + } + + em28xx_coredbg("dvb max packet size=%d\n", packet_size); + return packet_size; +} +EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize); + /* * em28xx_wake_i2c() * configure i2c attached devices diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index dd749442d..de919504f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -47,7 +47,6 @@ if (debug >= level) \ } while (0) #define EM28XX_DVB_NUM_BUFS 5 -#define EM28XX_DVB_MAX_PACKETSIZE 564 #define EM28XX_DVB_MAX_PACKETS 64 struct em28xx_dvb { @@ -143,14 +142,17 @@ static int start_streaming(struct em28xx_dvb *dvb) { int rc; struct em28xx *dev = dvb->adapter.priv; + int max_dvb_packet_size; usb_set_interface(dev->udev, 0, 1); rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); if (rc < 0) return rc; + max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); + return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, - EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE, + EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, dvb_isoc_copy); } diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 24e39c568..a2676d63c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -27,6 +27,22 @@ #define EM28XX_CHIPCFG_AC97 0x10 #define EM28XX_CHIPCFG_AUDIOMASK 0x30 +#define EM28XX_R01_CHIPCFG2 0x01 + +/* em28xx Chip Configuration 2 0x01 */ +#define EM28XX_CHIPCFG2_TS_PRESENT 0x10 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK 0x0c /* bits 3-2 */ +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF 0x00 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF 0x04 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF 0x08 +#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF 0x0c +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK 0x03 /* bits 0-1 */ +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188 0x00 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376 0x01 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564 0x02 +#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752 0x03 + + /* GPIO/GPO registers */ #define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ #define EM28XX_R08_GPIO 0x08 /* em2820 or upper */ diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 966a3b924..3403a45e8 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -625,6 +625,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, int num_bufs, int max_pkt_size, int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); void em28xx_uninit_isoc(struct em28xx *dev); +int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); void em28xx_wake_i2c(struct em28xx *dev); -- cgit v1.2.3 From 3e3ae9acd7a21aadc994ca194d5799c0cf441a7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 May 2009 19:27:16 +0000 Subject: Siano: smsusb - add big endien support From: Uri Shkolnik Add support for big endien target hosts, which use USB interface. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index 7f0246fdb..adeb920a5 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -78,6 +78,7 @@ static void smsusb_onresponse(struct urb *urb, struct pt_regs *regs) if ((urb->actual_length > 0) && (urb->status == 0)) { struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p; + smsendian_handle_message_header(phdr); if (urb->actual_length >= phdr->msgLength) { surb->cb->size = phdr->msgLength; -- cgit v1.2.3 From 99a8dbb1166ea0866ab85aa6990517d75c3d0cd6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 May 2009 19:28:17 +0000 Subject: Siano: move dvb-api headers' includes to dvb adapter From: Uri Shkolnik Move the DVB-API v3 headers' include list from the core component to the smsdvb (DVB adapter) which is the only one that uses them. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.h | 7 ------- linux/drivers/media/dvb/siano/smsdvb.c | 5 +++++ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index d98b4a749..0310c3a30 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -35,13 +35,6 @@ along with this program. If not, see . #include #include "compat.h" -#define SMS_DVB3_SUBSYS -#ifdef SMS_DVB3_SUBSYS -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#endif #define kmutex_init(_p_) mutex_init(_p_) #define kmutex_lock(_p_) mutex_lock(_p_) diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index f43c7f543..39421ee6f 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -22,6 +22,11 @@ along with this program. If not, see . #include #include +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" + #include "smscoreapi.h" #include "smsendian.h" #include "sms-cards.h" -- cgit v1.2.3 From 0d7f5cd403444bc4434d8bf726e528400f2a3926 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 May 2009 19:31:23 +0000 Subject: Siano: smscards - add gpio look-up table From: Uri Shkolnik Add gpio look-up table for various requirements, any target may select any gpio and assign it to a function Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/sms-cards.h | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h index 64d74c59c..5bd4fb4d3 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.h +++ b/linux/drivers/media/dvb/siano/sms-cards.h @@ -35,9 +35,43 @@ #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9 #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10 +struct sms_board_gpio_cfg { + int lna_vhf_exist; + int lna_vhf_ctrl; + int lna_uhf_exist; + int lna_uhf_ctrl; + int lna_uhf_d_ctrl; + int lna_sband_exist; + int lna_sband_ctrl; + int lna_sband_d_ctrl; + int foreign_lna0_ctrl; + int foreign_lna1_ctrl; + int foreign_lna2_ctrl; + int rf_switch_vhf; + int rf_switch_uhf; + int rf_switch_sband; + int leds_power; + int led0; + int led1; + int led2; + int led3; + int led4; + int ir; + int eeprom_wp; + int mrc_sense; + int mrc_pdn_resetn; + int mrc_gp0; /* mrcs spi int */ + int mrc_gp1; + int mrc_gp2; + int mrc_gp3; + int mrc_gp4; + int host_spi_gsp_ts_int; +}; + struct sms_board { enum sms_device_type_st type; char *name, *fw[DEVICE_MODE_MAX]; + struct sms_board_gpio_cfg board_cfg; /* gpios */ int led_power, led_hi, led_lo, lna_ctrl, rf_switch; -- cgit v1.2.3 From 11c31c4bd3cd328f0865ec402bf805372fbd6f22 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 May 2009 19:32:12 +0000 Subject: Siano: bind infra-red component From: Uri Shkolnik Add the infra-red to the makefile and declare the assignment in the cards components. Priority: normal [mchehab@redhat.com: Fixed a few trivial merge conflicts] Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/Makefile | 2 +- linux/drivers/media/dvb/siano/sms-cards.c | 1 + linux/drivers/media/dvb/siano/sms-cards.h | 4 ++++ linux/drivers/media/dvb/siano/smscoreapi.h | 3 ++- linux/drivers/media/dvb/siano/smsir.c | 24 ++++++++++++------------ 5 files changed, 20 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/Makefile b/linux/drivers/media/dvb/siano/Makefile index 6354a4718..c6644d909 100644 --- a/linux/drivers/media/dvb/siano/Makefile +++ b/linux/drivers/media/dvb/siano/Makefile @@ -1,4 +1,4 @@ -sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o +sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 63e4d0ec6..c35ff1f3f 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -18,6 +18,7 @@ */ #include "sms-cards.h" +#include "smsir.h" static int sms_dbg; module_param_named(cards_dbg, sms_dbg, int, 0644); diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h index 5bd4fb4d3..447481ab5 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.h +++ b/linux/drivers/media/dvb/siano/sms-cards.h @@ -22,6 +22,7 @@ #include #include "smscoreapi.h" +#include "smsir.h" #define SMS_BOARD_UNKNOWN 0 #define SMS1XXX_BOARD_SIANO_STELLAR 1 @@ -72,6 +73,7 @@ struct sms_board { enum sms_device_type_st type; char *name, *fw[DEVICE_MODE_MAX]; struct sms_board_gpio_cfg board_cfg; + enum ir_kb_type ir_kb_type; /* gpios */ int led_power, led_hi, led_lo, lna_ctrl, rf_switch; @@ -79,6 +81,8 @@ struct sms_board { struct sms_board *sms_get_board(int id); +extern struct smscore_device_t *coredev; + int sms_board_setup(struct smscore_device_t *coredev); #define SMS_LED_OFF 0 diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 0310c3a30..f4aa406ef 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -35,6 +35,7 @@ along with this program. If not, see . #include #include "compat.h" +#include "smsir.h" #define kmutex_init(_p_) mutex_init(_p_) #define kmutex_lock(_p_) mutex_lock(_p_) @@ -168,7 +169,7 @@ struct smscore_device_t { u32 fw_buf_size; /* Infrared (IR) */ - /* struct ir_t ir; */ + struct ir_t ir; int led_state; }; diff --git a/linux/drivers/media/dvb/siano/smsir.c b/linux/drivers/media/dvb/siano/smsir.c index a5f302c58..e3d776fee 100644 --- a/linux/drivers/media/dvb/siano/smsir.c +++ b/linux/drivers/media/dvb/siano/smsir.c @@ -99,7 +99,7 @@ static void sms_ir_rc5_event(struct smscore_device_t *coredev, bool toggle_changed; u16 keycode; - sms_info("IR RC5 word: address %d, command %d, toggle %d", + sms_log("IR RC5 word: address %d, command %d, toggle %d", addr, cmd, toggle); toggle_changed = ir_toggle != toggle; @@ -118,7 +118,7 @@ static void sms_ir_rc5_event(struct smscore_device_t *coredev, (keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN)) return; /* accept only repeated volume, reject other keys */ - sms_info("kernel input keycode (from ir) %d", keycode); + sms_log("kernel input keycode (from ir) %d", keycode); input_report_key(coredev->ir.input_dev, keycode, 1); input_sync(coredev->ir.input_dev); @@ -147,7 +147,7 @@ static u32 ir_rc5_decode(unsigned int code) break; case 3: /* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/ - sms_info("bad code"); + sms_log("bad code"); return 0; } } @@ -175,7 +175,7 @@ static void sms_rc5_parse_word(struct smscore_device_t *coredev) RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j) rc5_word = ir_rc5_decode(rc5_word); - /* sms_info("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */ + /* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */ sms_ir_rc5_event(coredev, RC5_TOGGLE(rc5_word), @@ -210,11 +210,11 @@ static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev, if (ir_pos == RC5_WORD_LEN) sms_rc5_parse_word(coredev); else if (ir_pos) /* timeout within a word */ - sms_info("IR error parsing a word"); + sms_log("IR error parsing a word"); ir_pos = 0; ir_word = 0; - /* sms_info("timeout %d", time); */ + /* sms_log("timeout %d", time); */ break; } /* The time is within the range of this number of bits */ @@ -236,7 +236,7 @@ void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) int count = len>>2; samples = (s32 *)buf; -/* sms_info("IR buffer received, length = %d", count);*/ +/* sms_log("IR buffer received, length = %d", count);*/ for (i = 0; i < count; i++) if (ir_protocol == IR_RC5) @@ -248,7 +248,7 @@ int sms_ir_init(struct smscore_device_t *coredev) { struct input_dev *input_dev; - sms_info("Allocating input device"); + sms_log("Allocating input device"); input_dev = input_allocate_device(); if (!input_dev) { sms_err("Not enough memory"); @@ -261,11 +261,11 @@ int sms_ir_init(struct smscore_device_t *coredev) coredev->ir.keyboard_layout_map = keyboard_layout_maps[coredev->ir.ir_kb_type]. keyboard_layout_map; - sms_info("IR remote keyboard type is %d", coredev->ir.ir_kb_type); + sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type); coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ coredev->ir.timeout = IR_DEFAULT_TIMEOUT; - sms_info("IR port %d, timeout %d ms", + sms_log("IR port %d, timeout %d ms", coredev->ir.controller, coredev->ir.timeout); snprintf(coredev->ir.name, @@ -280,7 +280,7 @@ int sms_ir_init(struct smscore_device_t *coredev) input_dev->evbit[0] = BIT_MASK(EV_KEY); input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); - sms_info("Input device (IR) %s is set for key events", input_dev->name); + sms_log("Input device (IR) %s is set for key events", input_dev->name); if (input_register_device(input_dev)) { sms_err("Failed to register device"); @@ -296,6 +296,6 @@ void sms_ir_exit(struct smscore_device_t *coredev) if (coredev->ir.input_dev) input_unregister_device(coredev->ir.input_dev); - sms_info(""); + sms_log(""); } -- cgit v1.2.3 From 0605798099a08b6dddc3c89ab0047146840eedea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 18 May 2009 03:58:54 -0300 Subject: date: Thu May 14 12:29:35 2009 -0700 From: Uri Shkolnik Siano: USB - move the device id table to the cards module The card modules is the component which handles various targets, so the IDs table should reside within it. Priority: normal [mchehab@redhat.com: add missing smsendian.h include at smscoreapi.c] Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 98 +++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 15272dbb5..c13d80698 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -33,6 +33,8 @@ #include "smscoreapi.h" #include "sms-cards.h" +#include "smsir.h" +#include "smsendian.h" static int sms_dbg; module_param_named(debug, sms_dbg, int, 0644); @@ -348,6 +350,7 @@ int smscore_register_device(struct smsdevice_params_t *params, init_completion(&dev->init_device_done); init_completion(&dev->reload_start_done); init_completion(&dev->resume_done); + init_completion(&dev->ir_init_done); /* alloc common buffer */ dev->common_buffer_size = params->buffer_size * params->num_buffers; @@ -403,6 +406,71 @@ int smscore_register_device(struct smsdevice_params_t *params, } EXPORT_SYMBOL_GPL(smscore_register_device); + +static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, + void *buffer, size_t size, struct completion *completion) { + int rc = coredev->sendrequest_handler(coredev->context, buffer, size); + if (rc < 0) { + sms_info("sendrequest returned error %d", rc); + return rc; + } + + return wait_for_completion_timeout(completion, + msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ? + 0 : -ETIME; +} + +/** + * Starts & enables IR operations + * + * @return 0 on success, < 0 on error. + */ +static int smscore_init_ir(struct smscore_device_t *coredev) +{ + int ir_io; + int rc; + void *buffer; + + coredev->ir.input_dev = NULL; + ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir; + if (ir_io) {/* only if IR port exist we use IR sub-module */ + sms_info("IR loading"); + rc = sms_ir_init(coredev); + + if (rc != 0) + sms_err("Error initialization DTV IR sub-module"); + else { + buffer = kmalloc(sizeof(struct SmsMsgData_ST2) + + SMS_DMA_ALIGNMENT, + GFP_KERNEL | GFP_DMA); + if (buffer) { + struct SmsMsgData_ST2 *msg = + (struct SmsMsgData_ST2 *) + SMS_ALIGN_ADDRESS(buffer); + + SMS_INIT_MSG(&msg->xMsgHeader, + MSG_SMS_START_IR_REQ, + sizeof(struct SmsMsgData_ST2)); + msg->msgData[0] = coredev->ir.controller; + msg->msgData[1] = coredev->ir.timeout; + + smsendian_handle_tx_message( + (struct SmsMsgHdr_ST2 *)msg); + rc = smscore_sendrequest_and_wait(coredev, msg, + msg->xMsgHeader. msgLength, + &coredev->ir_init_done); + + kfree(buffer); + } else + sms_err + ("Sending IR initialization message failed"); + } + } else + sms_info("IR port has not been detected"); + + return 0; +} + /** * sets initial device mode and notifies client hotplugs that device is ready * @@ -423,6 +491,7 @@ int smscore_start_device(struct smscore_device_t *coredev) kmutex_lock(&g_smscore_deviceslock); rc = smscore_notify_callbacks(coredev, coredev->device, 1); + smscore_init_ir(coredev); sms_info("device %p started, rc %d", coredev, rc); @@ -432,20 +501,6 @@ int smscore_start_device(struct smscore_device_t *coredev) } EXPORT_SYMBOL_GPL(smscore_start_device); -static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, - void *buffer, size_t size, - struct completion *completion) -{ - int rc = coredev->sendrequest_handler(coredev->context, buffer, size); - if (rc < 0) { - sms_info("sendrequest returned error %d", rc); - return rc; - } - - return wait_for_completion_timeout(completion, - msecs_to_jiffies(10000)) ? - 0 : -ETIME; -} static int smscore_load_firmware_family2(struct smscore_device_t *coredev, void *buffer, size_t size) @@ -621,6 +676,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev) kmutex_lock(&g_smscore_deviceslock); + /* Release input device (IR) resources */ + sms_ir_exit(coredev); + smscore_notify_clients(coredev); smscore_notify_callbacks(coredev, NULL, 0); @@ -980,6 +1038,18 @@ void smscore_onresponse(struct smscore_device_t *coredev, case MSG_SMS_SLEEP_RESUME_COMP_IND: complete(&coredev->resume_done); break; + case MSG_SMS_START_IR_RES: + complete(&coredev->ir_init_done); + break; + case MSG_SMS_IR_SAMPLES_IND: + sms_ir_event(coredev, + (const char *) + ((char *)phdr + + sizeof(struct SmsMsgHdr_ST)), + (int)phdr->msgLength + - sizeof(struct SmsMsgHdr_ST)); + break; + default: #if 0 sms_info("no client (%p) or error (%d), " -- cgit v1.2.3 From 8c5084621800a914e3ca5e6a35d2242d8c47143a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 May 2009 19:33:37 +0000 Subject: Siano: smscards - fix wrong firmware assignment From: Uri Shkolnik Remove wrong firmware assignments for Nova, Stellar Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/sms-cards.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index c35ff1f3f..b5dc36dc8 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -31,17 +31,14 @@ static struct sms_board sms_boards[] = { [SMS1XXX_BOARD_SIANO_STELLAR] = { .name = "Siano Stellar Digital Receiver", .type = SMS_STELLAR, - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw", }, [SMS1XXX_BOARD_SIANO_NOVA_A] = { .name = "Siano Nova A Digital Receiver", .type = SMS_NOVA_A0, - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw", }, [SMS1XXX_BOARD_SIANO_NOVA_B] = { .name = "Siano Nova B Digital Receiver", .type = SMS_NOVA_B0, - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw", }, [SMS1XXX_BOARD_SIANO_VEGA] = { .name = "Siano Vega Digital Receiver", -- cgit v1.2.3 From 8a53093333397ea670efada7f563c1c429f7481c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 May 2009 19:34:59 +0000 Subject: Siano: smscards - assign gpio to HPG targets From: Uri Shkolnik Assign using the new gpio structures, i/o for exist HPG targets, without removing the old implementation. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/sms-cards.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index b5dc36dc8..fda483f07 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -63,6 +63,9 @@ static struct sms_board sms_boards[] = { .name = "Hauppauge WinTV MiniStick", .type = SMS_NOVA_B0, .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", + .board_cfg.leds_power = 26, + .board_cfg.led0 = 27, + .board_cfg.led1 = 28, .led_power = 26, .led_lo = 27, .led_hi = 28, @@ -72,7 +75,9 @@ static struct sms_board sms_boards[] = { .type = SMS_NOVA_B0, .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", .lna_ctrl = 29, + .board_cfg.foreign_lna0_ctrl = 29, .rf_switch = 17, + .board_cfg.rf_switch_uhf = 17, }, [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { .name = "Hauppauge WinTV MiniCard", -- cgit v1.2.3 From 431384bb330ec2f151b2e44b3ecc85c61cdf0477 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 17 May 2009 08:59:37 +0000 Subject: Siano: smscore - fix get_common_buffer bug From: Uri Shkolnik get common buffers() should block operation until valid buffer is avaliable. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 38 +++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index c13d80698..c65c9196c 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -30,6 +30,7 @@ #include #include +#include #include "smscoreapi.h" #include "sms-cards.h" @@ -352,6 +353,9 @@ int smscore_register_device(struct smsdevice_params_t *params, init_completion(&dev->resume_done); init_completion(&dev->ir_init_done); + /* Buffer management */ + init_waitqueue_head(&dev->buffer_mng_waitq); + /* alloc common buffer */ dev->common_buffer_size = params->buffer_size * params->num_buffers; dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size, @@ -686,7 +690,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev) * onresponse must no longer be called */ while (1) { - while ((cb = smscore_getbuffer(coredev))) { + while (!list_empty(&coredev->buffers)) { + cb = (struct smscore_buffer_t *) coredev->buffers.next; + list_del(&cb->entry); kfree(cb); num_buffers++; } @@ -707,8 +713,10 @@ void smscore_unregister_device(struct smscore_device_t *coredev) if (coredev->common_buffer) dma_free_coherent(NULL, coredev->common_buffer_size, - coredev->common_buffer, - coredev->common_buffer_phys); + coredev->common_buffer, coredev->common_buffer_phys); + + if (coredev->fw_buf != NULL) + kfree(coredev->fw_buf); list_del(&coredev->entry); kfree(coredev); @@ -1076,12 +1084,24 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) struct smscore_buffer_t *cb = NULL; unsigned long flags; + DEFINE_WAIT(wait); + spin_lock_irqsave(&coredev->bufferslock, flags); - if (!list_empty(&coredev->buffers)) { - cb = (struct smscore_buffer_t *) coredev->buffers.next; - list_del(&cb->entry); - } + /* This function must return a valid buffer, since the buffer list is + * finite, we check that there is an available buffer, if not, we wait + * until such buffer become available. + */ + + prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE); + + if (list_empty(&coredev->buffers)) + schedule(); + + finish_wait(&coredev->buffer_mng_waitq, &wait); + + cb = (struct smscore_buffer_t *) coredev->buffers.next; + list_del(&cb->entry); spin_unlock_irqrestore(&coredev->bufferslock, flags); @@ -1098,8 +1118,8 @@ EXPORT_SYMBOL_GPL(smscore_getbuffer); * */ void smscore_putbuffer(struct smscore_device_t *coredev, - struct smscore_buffer_t *cb) -{ + struct smscore_buffer_t *cb) { + wake_up_interruptible(&coredev->buffer_mng_waitq); list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); } EXPORT_SYMBOL_GPL(smscore_putbuffer); -- cgit v1.2.3 From 4ffca8cce22602b296a5358e88a13811f9d9f272 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 17 May 2009 09:01:03 +0000 Subject: Siano: smscore - fix byte ordering bug From: Uri Shkolnik Fix byte ordering bug. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index c65c9196c..0f360d7ba 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -31,6 +31,7 @@ #include #include +#include #include "smscoreapi.h" #include "sms-cards.h" @@ -511,9 +512,13 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, { struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; struct SmsMsgHdr_ST *msg; - u32 mem_address = firmware->StartAddress; + u32 mem_address; u8 *payload = firmware->Payload; int rc = 0; + firmware->StartAddress = le32_to_cpu(firmware->StartAddress); + firmware->Length = le32_to_cpu(firmware->Length); + + mem_address = firmware->StartAddress; sms_info("loading FW to addr 0x%x size %d", mem_address, firmware->Length); -- cgit v1.2.3 From a201f474c8b7e9763bba588bdfc6fe757020a851 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 17 May 2009 09:01:55 +0000 Subject: Siano: smscore - fix isdb-t firmware name From: Uri Shkolnik Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 0f360d7ba..d31380b26 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -781,7 +781,7 @@ static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { /*BDA*/ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, /*ISDBT*/ - {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"}, + {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, /*ISDBTBDA*/ {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, /*CMMB*/ -- cgit v1.2.3 From 748341157e592566108cd3174bad52bdd3c3c07c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 17 May 2009 09:02:46 +0000 Subject: Siano: smscore - bug fix at get_device_mode From: Uri Shkolnik Fix bug that cause error log to echo also if success Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index d31380b26..16917016c 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -905,7 +905,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) coredev->device_flags &= ~SMS_DEVICE_NOT_READY; } - if (rc != 0) + if (rc < 0) sms_err("return error code %d.", rc); return rc; } -- cgit v1.2.3 From da327f1d8548abe9c1e49220e775407e2c7931f2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 17 May 2009 12:17:51 +0000 Subject: Siano: smsusb - fix typo in module description From: Uri Shkolnik Fix small typo in the module description Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index adeb920a5..4ffc55a03 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -566,6 +566,6 @@ void smsusb_module_exit(void) module_init(smsusb_module_init); module_exit(smsusb_module_exit); -MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle"); +MODULE_DESCRIPTION("Driver for the Siano SMS1xxx USB dongle"); MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 0afb58412d04348dc6819d5fe8da278c857d37ab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 17 May 2009 12:28:55 +0000 Subject: Siano: smsusb - change exit func debug msg From: Uri Shkolnik Change the debug message of the USB interface driver exit function. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index 4ffc55a03..3bbbdb197 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -558,9 +558,9 @@ int smsusb_module_init(void) void smsusb_module_exit(void) { - sms_debug(""); /* Regular USB Cleanup */ usb_deregister(&smsusb_driver); + sms_info("end"); } module_init(smsusb_module_init); -- cgit v1.2.3 From 39d53fcd39df81baf92cc74a0de40d5a1cbbd9bf Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 19 May 2009 15:08:03 +0200 Subject: uvcvideo: Start status polling on device open From: Laurent Pinchart Most UVC camera include an interrupt endpoint to report control value changes, video streaming errors and camera button events. The USB controller continuously polls the interrupt endpoint to retrieve such events. This prevents the device from being auto-suspended, and thus consumes power. Reporting video streaming errors don't make sense when the V4L2 device is closed. Control value changes are probably useless as well if nobody listens to the events, although caching will probably have to be completely disabled then. No polling is thus be required when /dev/videoX is not opened. To enable auto-suspend and save power do not poll the interrupt endpoint until the device is open. We lose the ability to detect button events if no application is using the camera. http://bugzilla.kernel.org/show_bug.cgi?id=11948 Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 1 + linux/drivers/media/video/uvc/uvc_status.c | 21 ++++++++++++++++++--- linux/drivers/media/video/uvc/uvc_v4l2.c | 14 ++++++++++++++ linux/drivers/media/video/uvc/uvcvideo.h | 3 +++ 4 files changed, 36 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 1768389c4..13bd05576 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1594,6 +1594,7 @@ static int uvc_probe(struct usb_interface *intf, INIT_LIST_HEAD(&dev->entities); INIT_LIST_HEAD(&dev->streaming); kref_init(&dev->kref); + atomic_set(&dev->users, 0); dev->udev = usb_get_dev(udev); dev->intf = usb_get_intf(intf); diff --git a/linux/drivers/media/video/uvc/uvc_status.c b/linux/drivers/media/video/uvc/uvc_status.c index 1e1bda413..b05df63b4 100644 --- a/linux/drivers/media/video/uvc/uvc_status.c +++ b/linux/drivers/media/video/uvc/uvc_status.c @@ -206,7 +206,7 @@ int uvc_status_init(struct uvc_device *dev) dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete, dev, interval); - return usb_submit_urb(dev->int_urb, GFP_KERNEL); + return 0; } void uvc_status_cleanup(struct uvc_device *dev) @@ -217,15 +217,30 @@ void uvc_status_cleanup(struct uvc_device *dev) uvc_input_cleanup(dev); } -int uvc_status_suspend(struct uvc_device *dev) +int uvc_status_start(struct uvc_device *dev) +{ + if (dev->int_urb == NULL) + return 0; + + return usb_submit_urb(dev->int_urb, GFP_KERNEL); +} + +void uvc_status_stop(struct uvc_device *dev) { usb_kill_urb(dev->int_urb); +} + +int uvc_status_suspend(struct uvc_device *dev) +{ + if (atomic_read(&dev->users)) + usb_kill_urb(dev->int_urb); + return 0; } int uvc_status_resume(struct uvc_device *dev) { - if (dev->int_urb == NULL) + if (dev->int_urb == NULL || atomic_read(&dev->users) == 0) return 0; return usb_submit_urb(dev->int_urb, GFP_NOIO); diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index bc13dbf05..160c01314 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -443,6 +443,17 @@ static int uvc_v4l2_open(struct file *file) goto done; } + if (atomic_inc_return(&video->dev->users) == 1) { + if ((ret = uvc_status_start(video->dev)) < 0) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) + usb_autopm_put_interface(video->dev->intf); +#endif + atomic_dec(&video->dev->users); + kfree(handle); + goto done; + } + } + handle->device = video; handle->state = UVC_HANDLE_PASSIVE; file->private_data = handle; @@ -477,6 +488,9 @@ static int uvc_v4l2_release(struct file *file) kfree(handle); file->private_data = NULL; + if (atomic_dec_return(&video->dev->users) == 0) + uvc_status_stop(video->dev); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) usb_autopm_put_interface(video->dev->intf); #endif diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 53d5c9e0c..6b254fd39 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -635,6 +635,7 @@ struct uvc_device { enum uvc_device_state state; struct kref kref; struct list_head list; + atomic_t users; /* Video control interface */ __u16 uvc_version; @@ -771,6 +772,8 @@ extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, /* Status */ extern int uvc_status_init(struct uvc_device *dev); extern void uvc_status_cleanup(struct uvc_device *dev); +extern int uvc_status_start(struct uvc_device *dev); +extern void uvc_status_stop(struct uvc_device *dev); extern int uvc_status_suspend(struct uvc_device *dev); extern int uvc_status_resume(struct uvc_device *dev); -- cgit v1.2.3 From 2da5cdaefead4beb36671ca025826f9e8deadef4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 19 May 2009 15:12:17 +0200 Subject: uvcvideo: Add Lenovo Thinkpad SL400 to device list comments From: Filipe Rosset Update the 17ef:480b device comment to list Lenovo Thinkpad SL400. Priority: low Signed-off-by: Filipe Rosset Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 13bd05576..177d149a5 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1907,7 +1907,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Lenovo Thinkpad SL500 */ + /* Lenovo Thinkpad SL400/SL500 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x17ef, -- cgit v1.2.3 From 77cae28861d7b7a3542ae1d487c8ac43245811e0 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 20 May 2009 09:57:10 +0200 Subject: Reducing print-level of I2C error prints From: Matthias Schwarzott Reducing the print-levle of I2C error prints cleans some unwanted but unavoidable errors from default syslog-level. Priority: normal Signed-off-by: Matthias Schwarzott Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/flexcop-i2c.c | 2 +- linux/drivers/media/dvb/frontends/mt312.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c index 06a90f67e..df4d6e8d9 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -200,7 +200,7 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1); if (ret < 0) { - err("i2c master_xfer failed"); + deb_i2c("i2c master_xfer failed"); break; } } diff --git a/linux/drivers/media/dvb/frontends/mt312.c b/linux/drivers/media/dvb/frontends/mt312.c index 5ac9b1592..a621f7279 100644 --- a/linux/drivers/media/dvb/frontends/mt312.c +++ b/linux/drivers/media/dvb/frontends/mt312.c @@ -77,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { - printk(KERN_ERR "%s: ret == %d\n", __func__, ret); + printk(KERN_DEBUG "%s: ret == %d\n", __func__, ret); return -EREMOTEIO; } -- cgit v1.2.3 From f947fc2a2490cb5bec7d536e4d7ab98b24e3e333 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 20 May 2009 10:08:26 +0200 Subject: Rewrote frontend-attach mechanism to gain noise-less deactivation of submodules From: Patrick Boettcher This patch is reorganizing the frontend-attach mechanism in order to gain noise-less (superflous prints) deactivation of submodules. Credits go to Uwe Bugla for helping to clean and test the code. Priority: normal Signed-off-by: Uwe Bugla Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/flexcop-common.h | 8 +- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 760 +++++++++++++----------- 2 files changed, 413 insertions(+), 355 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-common.h b/linux/drivers/media/dvb/b2c2/flexcop-common.h index cee2956cb..9d66105d3 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-common.h +++ b/linux/drivers/media/dvb/b2c2/flexcop-common.h @@ -1,9 +1,7 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-common.h - common header file for device-specific source files also. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-common.h - common header file for device-specific source files + * see flexcop.c for copyright information */ #ifndef __FLEXCOP_COMMON_H__ #define __FLEXCOP_COMMON_H__ diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index f7afab594..3f485bf13 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -1,34 +1,27 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-fe-tuner.c - methods for attaching a frontend and controlling DiSEqC. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling + * see flexcop.c for copyright information */ #include - #include "flexcop.h" - -#include "stv0299.h" -#include "mt352.h" -#include "nxt200x.h" -#include "bcm3510.h" -#include "stv0297.h" #include "mt312.h" -#include "lgdt330x.h" -#include "dvb-pll.h" -#include "tuner-simple.h" - +#include "stv0299.h" #include "s5h1420.h" #include "itd1000.h" - -#include "cx24123.h" #include "cx24113.h" - +#include "cx24123.h" #include "isl6421.h" +#include "mt352.h" +#include "bcm3510.h" +#include "nxt200x.h" +#include "dvb-pll.h" +#include "lgdt330x.h" +#include "tuner-simple.h" +#include "stv0297.h" /* lnb control */ - +#if defined(CONFIG_DVB_MT312_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct flexcop_device *fc = fe->dvb->priv; @@ -37,65 +30,62 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage v = fc->read_ibi_reg(fc, misc_204); switch (voltage) { - case SEC_VOLTAGE_OFF: - v.misc_204.ACPI1_sig = 1; - break; - case SEC_VOLTAGE_13: - v.misc_204.ACPI1_sig = 0; - v.misc_204.LNB_L_H_sig = 0; - break; - case SEC_VOLTAGE_18: - v.misc_204.ACPI1_sig = 0; - v.misc_204.LNB_L_H_sig = 1; - break; - default: - err("unknown SEC_VOLTAGE value"); - return -EINVAL; + case SEC_VOLTAGE_OFF: + v.misc_204.ACPI1_sig = 1; + break; + case SEC_VOLTAGE_13: + v.misc_204.ACPI1_sig = 0; + v.misc_204.LNB_L_H_sig = 0; + break; + case SEC_VOLTAGE_18: + v.misc_204.ACPI1_sig = 0; + v.misc_204.LNB_L_H_sig = 1; + break; + default: + err("unknown SEC_VOLTAGE value"); + return -EINVAL; } return fc->write_ibi_reg(fc, misc_204, v); } +#endif +#if defined(CONFIG_DVB_S5H1420_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) \ + || defined(CONFIG_DVB_MT312_MODULE) static int flexcop_sleep(struct dvb_frontend* fe) { struct flexcop_device *fc = fe->dvb->priv; -/* flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */ - if (fc->fe_sleep) return fc->fe_sleep(fe); - -/* v.misc_204.ACPI3_sig = 1; - fc->write_ibi_reg(fc,misc_204,v);*/ - return 0; } +#endif +/* SkyStar2 DVB-S rev 2.3 */ +#if defined(CONFIG_DVB_MT312_MODULE) static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) { - /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ +/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ struct flexcop_device *fc = fe->dvb->priv; flexcop_ibi_value v; u16 ax; v.raw = 0; - deb_tuner("tone = %u\n",tone); switch (tone) { - case SEC_TONE_ON: - ax = 0x01ff; - break; - case SEC_TONE_OFF: - ax = 0; - break; - default: - err("unknown SEC_TONE value"); - return -EINVAL; + case SEC_TONE_ON: + ax = 0x01ff; + break; + case SEC_TONE_OFF: + ax = 0; + break; + default: + err("unknown SEC_TONE value"); + return -EINVAL; } v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */ - v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax; v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax; - return fc->write_ibi_reg(fc,lnb_switch_freq_200,v); } @@ -110,17 +100,16 @@ static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data) static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data) { int i, par = 1, d; - for (i = 7; i >= 0; i--) { d = (data >> i) & 1; par ^= d; flexcop_diseqc_send_bit(fe, d); } - flexcop_diseqc_send_bit(fe, par); } -static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst) +static int flexcop_send_diseqc_msg(struct dvb_frontend *fe, + int len, u8 *msg, unsigned long burst) { int i; @@ -129,7 +118,6 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un for (i = 0; i < len; i++) flexcop_diseqc_send_byte(fe,msg[i]); - mdelay(16); if (burst != -1) { @@ -146,50 +134,110 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un return 0; } -static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) +static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *cmd) { return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0); } -static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +static int flexcop_diseqc_send_burst(struct dvb_frontend *fe, + fe_sec_mini_cmd_t minicmd) { return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd); } -/* dvb-s stv0299 */ -static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +static struct mt312_config skystar23_samsung_tbdu18132_config = { + .demod_address = 0x0e, +}; + +static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, + .len = sizeof(buf) }; + struct flexcop_device *fc = fe->dvb->priv; + div = (params->frequency + (125/2)) / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = (div >> 0) & 0xff; + buf[2] = 0x84 | ((div >> 10) & 0x60); + buf[3] = 0x80; + + if (params->frequency < 1550000) + buf[3] |= 0x02; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static void skystar2_rev23_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(mt312_attach, + &skystar23_samsung_tbdu18132_config, i2c); + if (fc->fe != NULL) { + struct dvb_frontend_ops *ops = &fc->fe->ops; + ops->tuner_ops.set_params \ + = skystar23_samsung_tbdu18132_tuner_set_params; + ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; + ops->diseqc_send_burst = flexcop_diseqc_send_burst; + ops->set_tone = flexcop_set_tone; + ops->set_voltage = flexcop_set_voltage; + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; + fc->dev_type = FC_SKY_REV23; + } +} +#endif + +/* SkyStar2 DVB-S rev 2.6 */ +#if defined(CONFIG_DVB_STV0299_MODULE) +static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe, + u32 srate, u32 ratio) { u8 aclk = 0; u8 bclk = 0; - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg (fe, 0x13, aclk); - stv0299_writereg (fe, 0x14, bclk); - stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + if (srate < 1500000) { + aclk = 0xb7; bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; bclk = 0x51; + } + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, ratio & 0xf0); return 0; } -static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) +static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { u8 buf[4]; u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct i2c_msg msg = { + .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; struct flexcop_device *fc = fe->dvb->priv; - div = params->frequency / 125; buf[0] = (div >> 8) & 0x7f; buf[1] = div & 0xff; - buf[2] = 0x84; /* 0xC4 */ + buf[2] = 0x84; /* 0xC4 */ buf[3] = 0x08; if (params->frequency < 1500000) @@ -203,48 +251,48 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv } static u8 samsung_tbmu24112_inittab[] = { - 0x01, 0x15, - 0x02, 0x30, - 0x03, 0x00, - 0x04, 0x7D, - 0x05, 0x35, - 0x06, 0x02, - 0x07, 0x00, - 0x08, 0xC3, - 0x0C, 0x00, - 0x0D, 0x81, - 0x0E, 0x23, - 0x0F, 0x12, - 0x10, 0x7E, - 0x11, 0x84, - 0x12, 0xB9, - 0x13, 0x88, - 0x14, 0x89, - 0x15, 0xC9, - 0x16, 0x00, - 0x17, 0x5C, - 0x18, 0x00, - 0x19, 0x00, - 0x1A, 0x00, - 0x1C, 0x00, - 0x1D, 0x00, - 0x1E, 0x00, - 0x1F, 0x3A, - 0x20, 0x2E, - 0x21, 0x80, - 0x22, 0xFF, - 0x23, 0xC1, - 0x28, 0x00, - 0x29, 0x1E, - 0x2A, 0x14, - 0x2B, 0x0F, - 0x2C, 0x09, - 0x2D, 0x05, - 0x31, 0x1F, - 0x32, 0x19, - 0x33, 0xFE, - 0x34, 0x93, - 0xff, 0xff, + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7D, + 0x05, 0x35, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0xC3, + 0x0C, 0x00, + 0x0D, 0x81, + 0x0E, 0x23, + 0x0F, 0x12, + 0x10, 0x7E, + 0x11, 0x84, + 0x12, 0xB9, + 0x13, 0x88, + 0x14, 0x89, + 0x15, 0xC9, + 0x16, 0x00, + 0x17, 0x5C, + 0x18, 0x00, + 0x19, 0x00, + 0x1A, 0x00, + 0x1C, 0x00, + 0x1D, 0x00, + 0x1E, 0x00, + 0x1F, 0x3A, + 0x20, 0x2E, + 0x21, 0x80, + 0x22, 0xFF, + 0x23, 0xC1, + 0x28, 0x00, + 0x29, 0x1E, + 0x2A, 0x14, + 0x2B, 0x0F, + 0x2C, 0x09, + 0x2D, 0x05, + 0x31, 0x1F, + 0x32, 0x19, + 0x33, 0xFE, + 0x34, 0x93, + 0xff, 0xff, }; static struct stv0299_config samsung_tbmu24112_config = { @@ -259,27 +307,136 @@ static struct stv0299_config samsung_tbmu24112_config = { .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, }; -/* dvb-t mt352 */ -static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) +static void skystar2_rev26_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) { - static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d }; - static u8 mt352_reset [] = { 0x50, 0x80 }; - static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; - static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 }; + fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); + if (fc->fe != NULL) { + struct dvb_frontend_ops *ops = &fc->fe->ops; + ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params; + ops->set_voltage = flexcop_set_voltage; + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; + } +} +#endif + +/* SkyStar2 DVB-S rev 2.7 */ +#if defined(CONFIG_DVB_S5H1420_MODULE) +static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { + .demod_address = 0x53, + .invert = 1, + .repeated_start_workaround = 1, + .serial_mpeg = 1, +}; + +static struct itd1000_config skystar2_rev2_7_itd1000_config = { + .i2c_address = 0x61, +}; + +static void skystar2_rev27_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + /* enable no_base_addr - no repeated start when reading */ + fc->fc_i2c_adap[0].no_base_addr = 1; + fc->fe = dvb_attach(s5h1420_attach, + &skystar2_rev2_7_s5h1420_config, i2c); + if (fc->fe != NULL) { + flexcop_ibi_value r108; + struct i2c_adapter *i2c_tuner \ + = s5h1420_get_tuner_i2c_adapter(fc->fe); + struct dvb_frontend_ops *ops = &fc->fe->ops; + + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; + + /* enable no_base_addr - no repeated start when reading */ + fc->fc_i2c_adap[2].no_base_addr = 1; + if (dvb_attach(isl6421_attach, fc->fe, + &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL) + err("ISL6421 could NOT be attached"); + else + info("ISL6421 successfully attached"); + + /* the ITD1000 requires a lower i2c clock - is it a problem ? */ + r108.raw = 0x00000506; + fc->write_ibi_reg(fc, tw_sm_c_108, r108); + if (i2c_tuner) { + if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, + &skystar2_rev2_7_itd1000_config) == NULL) + err("ITD1000 could NOT be attached"); + else + info("ITD1000 successfully attached"); + } + } else + fc->fc_i2c_adap[0].no_base_addr = 0; + /* for the next devices we need it again */ +} +#endif + +/* SkyStar2 rev 2.8 */ +#if defined(CONFIG_DVB_CX24123_MODULE) +static struct cx24123_config skystar2_rev2_8_cx24123_config = { + .demod_address = 0x55, + .dont_use_pll = 1, + .agc_callback = cx24113_agc_callback, +}; + +static const struct cx24113_config skystar2_rev2_8_cx24113_config = { + .i2c_addr = 0x54, + .xtal_khz = 10111, +}; + +static void skystar2_rev28_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(cx24123_attach, + &skystar2_rev2_8_cx24123_config, i2c); + if (fc->fe != NULL) { + struct i2c_adapter *i2c_tuner \ + = cx24123_get_tuner_i2c_adapter(fc->fe); + if (i2c_tuner != NULL) { + if (dvb_attach(cx24113_attach, fc->fe, + &skystar2_rev2_8_cx24113_config, + i2c_tuner) == NULL) + err("CX24113 could NOT be attached"); + else + info("CX24113 successfully attached"); + } + + fc->fc_i2c_adap[2].no_base_addr = 1; + if (dvb_attach(isl6421_attach, fc->fe, + &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL) + err("ISL6421 could NOT be attached"); + else + info("ISL6421 successfully attached"); + /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an + * IR-receiver (PIC16F818) - but the card has no input for that ??? */ + } +} +#endif + +/* AirStar DVB-T */ +#if defined(CONFIG_DVB_MT352_MODULE) +static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe) +{ + static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d }; + static u8 mt352_reset[] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 }; static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); udelay(2000); mt352_write(fe, mt352_reset, sizeof(mt352_reset)); mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - return 0; } -static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) +static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) { u32 div; unsigned char bs = 0; @@ -287,19 +444,20 @@ static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_fro if (buf_len < 5) return -EINVAL; - #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ +#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; - - if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09; - if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a; - if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08; + if (params->frequency >= 48000000 && params->frequency <= 154000000) \ + bs = 0x09; + if (params->frequency >= 161000000 && params->frequency <= 439000000) \ + bs = 0x0a; + if (params->frequency >= 447000000 && params->frequency <= 863000000) \ + bs = 0x08; pllbuf[0] = 0x61; pllbuf[1] = div >> 8; pllbuf[2] = div & 0xff; pllbuf[3] = 0xcc; pllbuf[4] = bs; - return 5; } @@ -308,70 +466,88 @@ static struct mt352_config samsung_tdtc9251dh0_config = { .demod_init = samsung_tdtc9251dh0_demod_init, }; -static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) +static void airstar_dvbt_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); + if (fc->fe != NULL) + fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; +} +#endif + +/* AirStar ATSC 1st generation */ +#if defined(CONFIG_DVB_BCM3510_MODULE) +static int flexcop_fe_request_firmware(struct dvb_frontend *fe, + const struct firmware **fw, char* name) { struct flexcop_device *fc = fe->dvb->priv; return request_firmware(fw, name, fc->dev); } -static struct lgdt330x_config air2pc_atsc_hd5000_config = { - .demod_address = 0x59, - .demod_chip = LGDT3303, - .serial_mpeg = 0x04, - .clock_polarity_flip = 1, -}; - -static struct nxt200x_config samsung_tbmv_config = { - .demod_address = 0x0a, -}; - static struct bcm3510_config air2pc_atsc_first_gen_config = { .demod_address = 0x0f, .request_firmware = flexcop_fe_request_firmware, }; -static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) +static void airstar_atsc1_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) { - u8 buf[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; - struct flexcop_device *fc = fe->dvb->priv; - - div = (params->frequency + (125/2)) / 125; - - buf[0] = (div >> 8) & 0x7f; - buf[1] = (div >> 0) & 0xff; - buf[2] = 0x84 | ((div >> 10) & 0x60); - buf[3] = 0x80; + fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); +} +#endif - if (params->frequency < 1550000) - buf[3] |= 0x02; +/* AirStar ATSC 2nd generation */ +#if defined(CONFIG_DVB_NXT200X_MODULE) +static struct nxt200x_config samsung_tbmv_config = { + .demod_address = 0x0a, +}; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1) - return -EIO; - return 0; +static void airstar_atsc2_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); + if (fc->fe != NULL) + dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, + DVB_PLL_SAMSUNG_TBMV); } +#endif -static struct mt312_config skystar23_samsung_tbdu18132_config = { - - .demod_address = 0x0e, +/* AirStar ATSC 3rd generation */ +#if defined(CONFIG_DVB_LGDT330X_MODULE) +static struct lgdt330x_config air2pc_atsc_hd5000_config = { + .demod_address = 0x59, + .demod_chip = LGDT3303, + .serial_mpeg = 0x04, + .clock_polarity_flip = 1, }; +static void airstar_atsc3_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) +{ + fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); + if (fc->fe != NULL) { + dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, + TUNER_LG_TDVS_H06XF); + } +} +#endif + +/* CableStar2 DVB-C */ +#if defined(CONFIG_DVB_STV0297_MODULE) static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) + struct dvb_frontend_parameters *fep) { struct flexcop_device *fc = fe->dvb->priv; u8 buf[4]; u16 div; int ret; -/* 62.5 kHz * 10 */ +/* 62.5 kHz * 10 */ #define REF_FREQ 625 #define FREQ_OFFSET 36125 - div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10) / REF_FREQ; // 4 MHz = 4000 KHz + div = ((fep->frequency/1000 + FREQ_OFFSET) * 10) / REF_FREQ; +/* 4 MHz = 4000 KHz */ buf[0] = (u8)( div >> 8) & 0x7f; buf[1] = (u8) div & 0xff; @@ -384,11 +560,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */ buf[2] = 0x95; -// Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5 -// 47 - 153 0 * 0 0 0 0 0 1 0x01 -// 153 - 430 0 * 0 0 0 0 1 0 0x02 -// 430 - 822 0 * 0 0 1 0 0 0 0x08 -// 822 - 862 1 * 0 0 1 0 0 0 0x88 +/* Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5 + * 47 - 153 0 * 0 0 0 0 0 1 0x01 + * 153 - 430 0 * 0 0 0 0 1 0 0x02 + * 430 - 822 0 * 0 0 1 0 0 0 0x08 + * 822 - 862 1 * 0 0 1 0 0 0 0x88 */ if (fep->frequency <= 153000000) buf[3] = 0x01; else if (fep->frequency <= 430000000) buf[3] = 0x02; @@ -397,11 +573,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); - deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]); + deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n", fep->frequency, + buf[0], buf[1], buf[2], buf[3]); ret = fc->i2c_request(&fc->fc_i2c_adap[2], - FC_WRITE, 0x61, buf[0], &buf[1], 3); + FC_WRITE, 0x61, buf[0], &buf[1], 3); deb_tuner("tuner write returned: %d\n",ret); - return ret; } @@ -481,190 +657,75 @@ static u8 alps_tdee4_stv0297_inittab[] = { static struct stv0297_config alps_tdee4_stv0297_config = { .demod_address = 0x1c, .inittab = alps_tdee4_stv0297_inittab, -// .invert = 1, -// .pll_set = alps_tdee4_stv0297_pll_set, }; - -/* SkyStar2 rev2.7 (a/u) */ -static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { - .demod_address = 0x53, - .invert = 1, - .repeated_start_workaround = 1, - .serial_mpeg = 1, -}; - -static struct itd1000_config skystar2_rev2_7_itd1000_config = { - .i2c_address = 0x61, -}; - -/* SkyStar2 rev2.8 */ -static struct cx24123_config skystar2_rev2_8_cx24123_config = { - .demod_address = 0x55, - .dont_use_pll = 1, - .agc_callback = cx24113_agc_callback, -}; - -static const struct cx24113_config skystar2_rev2_8_cx24113_config = { - .i2c_addr = 0x54, - .xtal_khz = 10111, -}; - -/* try to figure out the frontend, each card/box can have on of the following list */ -int flexcop_frontend_init(struct flexcop_device *fc) +static void cablestar2_attach(struct flexcop_device *fc, + struct i2c_adapter *i2c) { - struct dvb_frontend_ops *ops; - struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap; - struct i2c_adapter *i2c_tuner; - - /* enable no_base_addr - no repeated start when reading */ - fc->fc_i2c_adap[0].no_base_addr = 1; - fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c); - if (fc->fe != NULL) { - flexcop_ibi_value r108; - i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe); - ops = &fc->fe->ops; - - fc->fe_sleep = ops->sleep; - ops->sleep = flexcop_sleep; - - fc->dev_type = FC_SKY_REV27; - - /* enable no_base_addr - no repeated start when reading */ - fc->fc_i2c_adap[2].no_base_addr = 1; - if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL) - err("ISL6421 could NOT be attached"); - else - info("ISL6421 successfully attached"); - - /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */ - r108.raw = 0x00000506; - fc->write_ibi_reg(fc, tw_sm_c_108, r108); - if (i2c_tuner) { - if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL) - err("ITD1000 could NOT be attached"); - else - info("ITD1000 successfully attached"); - } - goto fe_found; - } - fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */ - - /* try the sky v2.8 (cx24123, isl6421) */ - fc->fe = dvb_attach(cx24123_attach, - &skystar2_rev2_8_cx24123_config, i2c); - if (fc->fe != NULL) { - i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe); - if (i2c_tuner != NULL) { - if (dvb_attach(cx24113_attach, fc->fe, - &skystar2_rev2_8_cx24113_config, - i2c_tuner) == NULL) - err("CX24113 could NOT be attached"); - else - info("CX24113 successfully attached"); - } - - fc->dev_type = FC_SKY_REV28; - - fc->fc_i2c_adap[2].no_base_addr = 1; - if (dvb_attach(isl6421_attach, fc->fe, - &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL) - err("ISL6421 could NOT be attached"); - else - info("ISL6421 successfully attached"); - - /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an - * IR-receiver (PIC16F818) - but the card has no input for - * that ??? */ - - goto fe_found; - } - - /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ - fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); - if (fc->fe != NULL) { - ops = &fc->fe->ops; - - ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params; - - ops->set_voltage = flexcop_set_voltage; - - fc->fe_sleep = ops->sleep; - ops->sleep = flexcop_sleep; - - fc->dev_type = FC_SKY_REV26; - goto fe_found; - } - - /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */ - fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_AIR_DVBT; - fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; - goto fe_found; - } - - /* try the air atsc 2nd generation (nxt2002) */ - fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_AIR_ATSC2; - dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV); - goto fe_found; - } - - fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_AIR_ATSC3; - dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, - TUNER_LG_TDVS_H06XF); - goto fe_found; - } - - /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ - fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_AIR_ATSC1; - goto fe_found; - } - - /* try the cable dvb (stv0297) */ fc->fc_i2c_adap[0].no_base_addr = 1; fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); - if (fc->fe != NULL) { - fc->dev_type = FC_CABLE; - fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; - goto fe_found; - } - fc->fc_i2c_adap[0].no_base_addr = 0; - - /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ - fc->fe = dvb_attach(mt312_attach, - &skystar23_samsung_tbdu18132_config, i2c); - if (fc->fe != NULL) { - ops = &fc->fe->ops; - - ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params; - - ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; - ops->diseqc_send_burst = flexcop_diseqc_send_burst; - ops->set_tone = flexcop_set_tone; - ops->set_voltage = flexcop_set_voltage; - - fc->fe_sleep = ops->sleep; - ops->sleep = flexcop_sleep; + if (fc->fe != NULL) + fc->fe->ops.tuner_ops.set_params \ + = alps_tdee4_stv0297_tuner_set_params; + else + fc->fc_i2c_adap[0].no_base_addr = 0; +} +#endif + +static struct { + flexcop_device_type_t type; + void (*attach)(struct flexcop_device *, struct i2c_adapter *); +} flexcop_frontends[] = { +#if defined(CONFIG_DVB_S5H1420_MODULE) + { FC_SKY_REV27, skystar2_rev27_attach }, +#endif +#if defined(CONFIG_DVB_CX24123_MODULE) + { FC_SKY_REV28, skystar2_rev28_attach }, +#endif +#if defined(CONFIG_DVB_STV0299_MODULE) + { FC_SKY_REV26, skystar2_rev26_attach }, +#endif +#if defined(CONFIG_DVB_MT352_MODULE) + { FC_AIR_DVBT, airstar_dvbt_attach }, +#endif +#if defined(CONFIG_DVB_NXT200X_MODULE) + { FC_AIR_ATSC2, airstar_atsc2_attach }, +#endif +#if defined(CONFIG_DVB_LGDT330X_MODULE) + { FC_AIR_ATSC3, airstar_atsc3_attach }, +#endif +#if defined(CONFIG_DVB_BCM3510_MODULE) + { FC_AIR_ATSC1, airstar_atsc1_attach }, +#endif +#if defined(CONFIG_DVB_STV0297_MODULE) + { FC_CABLE, cablestar2_attach }, +#endif +#if defined(CONFIG_DVB_MT312_MODULE) + { FC_SKY_REV23, skystar2_rev23_attach }, +#endif +}; - fc->dev_type = FC_SKY_REV23; - goto fe_found; +/* try to figure out the frontend */ +int flexcop_frontend_init(struct flexcop_device *fc) +{ + int i; + for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) { + /* type needs to be set before, because of some workarounds + * done based on the probed card type */ + fc->dev_type = flexcop_frontends[i].type; + flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap); + if (fc->fe != NULL) + goto fe_found; } - + fc->dev_type = FC_UNK; err("no frontend driver found for this B2C2/FlexCop adapter"); return -ENODEV; fe_found: info("found '%s' .", fc->fe->ops.info.name); if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { + struct dvb_frontend_ops *ops = &fc->fe->ops; err("frontend registration failed!"); - ops = &fc->fe->ops; if (ops->release != NULL) ops->release(fc->fe); fc->fe = NULL; @@ -680,6 +741,5 @@ void flexcop_frontend_exit(struct flexcop_device *fc) dvb_unregister_frontend(fc->fe); dvb_frontend_detach(fc->fe); } - fc->init_state &= ~FC_STATE_FE_INIT; } -- cgit v1.2.3 From 6d72be3d96a2a76833b5e2ef54b83ab0f9cb152e Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 20 May 2009 10:28:05 +0200 Subject: [PATCH] Leadtek WinFast DTV Dongle H From: tomas petr "Leadtek WinFast DTV Dongle H" is a hybrid digital/analog USB-stick TV receiver. The code below allows the digital part to work with dvb_usb in linux. Priority: normal Signed-off-by: tomas petr Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 8 +++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index ac97b9f42..d309ff7cc 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1498,6 +1498,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) }, { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) }, /* 50 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_Dlx) }, + { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_H) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1821,7 +1822,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 7, + .num_device_descs = 8, .devices = { { "Terratec Cinergy HT USB XE", { &dib0700_usb_id_table[27], NULL }, @@ -1851,6 +1852,11 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[48], NULL }, { NULL }, }, + { "Leadtek WinFast DTV Dongle H", + { &dib0700_usb_id_table[51], NULL }, + { NULL }, + }, + }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 1b5e65f1d..07227979e 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -225,6 +225,7 @@ #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 +#define USB_PID_WINFAST_DTV_DONGLE_H 0x60f6 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 #define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029 #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 -- cgit v1.2.3 From 6e94aca63322b3d936465135c50d873d53b56c93 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 20 May 2009 10:35:02 +0200 Subject: Added USB IDs for Terratec T3 and T5 From: Patrick Boettcher This patch adds the USB IDs for the Terratec devices T3 and T5. Priority: normal Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 12 ++++++++---- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index d309ff7cc..eda025714 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1499,6 +1499,8 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) }, /* 50 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_Dlx) }, { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_H) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1732,8 +1734,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[30], NULL }, { NULL }, }, - { "Terratec Cinergy T USB XXS", - { &dib0700_usb_id_table[33], NULL }, + { "Terratec Cinergy T USB XXS/ T3", + { &dib0700_usb_id_table[33], + &dib0700_usb_id_table[52], NULL }, { NULL }, }, { "Elgato EyeTV DTT", @@ -1794,8 +1797,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[36], NULL }, { NULL }, }, - { "Terratec Cinergy DT USB XS Diversity", - { &dib0700_usb_id_table[43], NULL }, + { "Terratec Cinergy DT USB XS Diversity/ T5", + { &dib0700_usb_id_table[43], + &dib0700_usb_id_table[53], NULL}, { NULL }, }, { "Sony PlayTV", diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 07227979e..7340ef4cd 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -181,6 +181,8 @@ #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 +#define USB_PID_TERRATEC_T3 0x10a0 +#define USB_PID_TERRATEC_T5 0x10a1 #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 -- cgit v1.2.3 From 7965383d6db294fc173ab00dd9f407f4af871ef7 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 20 May 2009 10:42:33 +0200 Subject: DIBUSB_MC : fix i2c to not corrupt eeprom in case of strange read pattern From: matthieu castet dibusb_i2c_xfer seems to do things very dangerous : it assumes that it get only write/read request or write request. That means that read can be understood as write. For example a program doing file = open("/dev/i2c-x", O_RDWR); ioctl(file, I2C_SLAVE, 0x50) read(file, data, 10) will corrupt the eeprom as it will be understood as a write. Priority: normal Signed-off-by: Matthieu CASTET Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/dibusb-common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c index d774879df..99b3b9a43 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -133,14 +133,17 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num for (i = 0; i < num; i++) { /* write/read request */ - if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { + if (i+1 < num && (msg[i].flags & I2C_M_RD) == 0 + && (msg[i+1].flags & I2C_M_RD)) { if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len, msg[i+1].buf,msg[i+1].len) < 0) break; i++; - } else + } else if ((msg[i].flags & I2C_M_RD) == 0) { if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) break; + } else + break; } mutex_unlock(&d->i2c_mutex); -- cgit v1.2.3 From abdeb4f3e7f1f6ec9cd4f59ad2d1eaabfea6d2a5 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 20 May 2009 10:52:13 +0200 Subject: Remove support for Genpix-CW3K (damages hardware) From: Alan Nisota I have been informed by the manufacturer that the patch currently in the v4l tree to support the Genpix-CW3K version of the hardware will actually damage the firmware on recent units. As he seems to not want this hardware supported in Linux, and I do not know how to detect the difference between affected and not-affected units, I am requesting the immediate removal of support for this device. This patch removes a portion of the changeset dce7e08ed2b1 applied 2007-08-18 relating to this specific device. Adapted patch to not remove code, but to only to comment it out. Priority: normal Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/gp8psk.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk.c b/linux/drivers/media/dvb/dvb-usb/gp8psk.c index 3dd684386..003d97f8c 100644 --- a/linux/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.c @@ -223,7 +223,7 @@ static struct usb_device_id gp8psk_usb_table [] = { { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) }, - { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, +/* { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */ { 0 }, }; MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); @@ -254,7 +254,7 @@ static struct dvb_usb_device_properties gp8psk_properties = { .generic_bulk_ctrl_endpoint = 0x01, - .num_device_descs = 4, + .num_device_descs = 3, .devices = { { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", .cold_ids = { &gp8psk_usb_table[0], NULL }, @@ -268,10 +268,12 @@ static struct dvb_usb_device_properties gp8psk_properties = { .cold_ids = { NULL }, .warm_ids = { &gp8psk_usb_table[3], NULL }, }, +#if 0 { .name = "Genpix SkyWalker-CW3K DVB-S receiver", .cold_ids = { NULL }, .warm_ids = { &gp8psk_usb_table[4], NULL }, }, +#endif { NULL }, } }; -- cgit v1.2.3 From 2e02dfe7b2fb1d1e4f2ac047fae75df83bdd3042 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 May 2009 09:58:52 -0300 Subject: em28xx: add Terratec Grabby From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 18 ++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 19 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index fb83e4f6e..088096def 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1412,6 +1412,22 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, } }, }, + [EM2860_BOARD_TERRATEC_GRABBY] = { + .name = "Terratec Grabby", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_SAA711X, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO2, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_VIDEO2, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1479,6 +1495,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2870_BOARD_TERRATEC_XS }, { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, + { USB_DEVICE(0x0ccd, 0x0096), + .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, { USB_DEVICE(0x185b, 0x2870), .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE }, { USB_DEVICE(0x185b, 0x2041), diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 3403a45e8..ba96a2a37 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -104,6 +104,7 @@ #define EM2860_BOARD_EASYCAP 64 #define EM2820_BOARD_IODATA_GVMVP_SZ 65 #define EM2880_BOARD_EMPIRE_DUAL_TV 66 +#define EM2860_BOARD_TERRATEC_GRABBY 67 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From 6179574749a379de2bfd3ee4f5496cc2ffc35218 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 24 May 2009 00:46:01 -0300 Subject: Add support for Terratec Grabster AV350 From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 32 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 33 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 088096def..1dff7528a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -153,6 +153,16 @@ static struct em28xx_reg_seq compro_mute_gpio[] = { { -1, -1, -1, -1}, }; +/* Terratec AV350 */ +static struct em28xx_reg_seq terratec_av350_mute_gpio[] = { + {EM28XX_R08_GPIO, 0xff, 0x7f, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { + {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + { -1, -1, -1, -1}, +}; /* * Board definitions */ @@ -1428,6 +1438,26 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO2, } }, }, + [EM2860_BOARD_TERRATEC_AV350] = { + .name = "Terratec AV350", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_TVP5150, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .mute_gpio = terratec_av350_mute_gpio, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AUDIO_SRC_LINE, + .gpio = terratec_av350_unmute_gpio, + + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AUDIO_SRC_LINE, + .gpio = terratec_av350_unmute_gpio, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1495,6 +1525,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2870_BOARD_TERRATEC_XS }, { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, + { USB_DEVICE(0x0ccd, 0x0084), + .driver_info = EM2860_BOARD_TERRATEC_AV350 }, { USB_DEVICE(0x0ccd, 0x0096), .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, { USB_DEVICE(0x185b, 0x2870), diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index ba96a2a37..1bb4a8242 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -105,6 +105,7 @@ #define EM2820_BOARD_IODATA_GVMVP_SZ 65 #define EM2880_BOARD_EMPIRE_DUAL_TV 66 #define EM2860_BOARD_TERRATEC_GRABBY 67 +#define EM2860_BOARD_TERRATEC_AV350 68 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From b474230d34df50ee4b5f01a6264ffb2d41dc5f9e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 11 May 2009 14:00:20 +0000 Subject: change kmalloc to vmalloc for sglist allocation in videobuf_dma_map/unmap From: Cohen David.A Change kmalloc()/kfree() to vmalloc()/vfree() for sglist allocation during videobuf_dma_map() and videobuf_dma_unmap() High resolution sensors might require too many contiguous pages to be allocated for sglist by kmalloc() during videobuf_dma_map() (i.e. 256Kib for 8MP sensor). In such situations, kmalloc() could face some problem to find the required free memory. vmalloc() is a safer solution instead, as the allocated memory does not need to be contiguous. Signed-off-by: David Cohen Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/videobuf-dma-sg.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/videobuf-dma-sg.c b/linux/drivers/media/video/videobuf-dma-sg.c index ed38145e1..623e2fc12 100644 --- a/linux/drivers/media/video/videobuf-dma-sg.c +++ b/linux/drivers/media/video/videobuf-dma-sg.c @@ -59,9 +59,10 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) struct page *pg; int i; - sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL); + sglist = vmalloc(nr_pages * sizeof(*sglist)); if (NULL == sglist) return NULL; + memset(sglist, 0, nr_pages * sizeof(*sglist)); sg_init_table(sglist, nr_pages); for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { pg = vmalloc_to_page(virt); @@ -73,7 +74,7 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) return sglist; err: - kfree(sglist); + vfree(sglist); return NULL; } @@ -85,7 +86,7 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) if (NULL == pages[0]) return NULL; - sglist = kmalloc(nr_pages * sizeof(*sglist), GFP_KERNEL); + sglist = vmalloc(nr_pages * sizeof(*sglist)); if (NULL == sglist) return NULL; sg_init_table(sglist, nr_pages); @@ -105,12 +106,12 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) nopage: dprintk(2,"sgl: oops - no page\n"); - kfree(sglist); + vfree(sglist); return NULL; highmem: dprintk(2,"sgl: oops - highmem page\n"); - kfree(sglist); + vfree(sglist); return NULL; } @@ -231,7 +232,7 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) (dma->vmalloc,dma->nr_pages); } if (dma->bus_addr) { - dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); + dma->sglist = vmalloc(sizeof(*dma->sglist)); if (NULL != dma->sglist) { dma->sglen = 1; sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK; @@ -249,7 +250,7 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) if (0 == dma->sglen) { printk(KERN_WARNING "%s: videobuf_map_sg failed\n",__func__); - kfree(dma->sglist); + vfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; return -EIO; @@ -275,7 +276,7 @@ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); - kfree(dma->sglist); + vfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; return 0; -- cgit v1.2.3 From 3e94e24e59b323cdacd22598b28769753866bfc3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 20:39:28 +0000 Subject: core: fix potential mutex_unlock without mutex_lock in dvb_dvr_read From: Simon Arlott dvb_dvr_read may unlock the dmxdev mutex and return -ENODEV, except this function is a file op and will never be called with the mutex held. There's existing mutex_lock and mutex_unlock around the actual read but it's commented out. These should probably be uncommented but the read blocks and this could block another non-blocking reader on the mutex instead. This change comments out the extra mutex_unlock. [akpm@linux-foundation.org: cleanups, simplification] Signed-off-by: Simon Arlott Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dmxdev.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.c b/linux/drivers/media/dvb/dvb-core/dmxdev.c index c35fbb8d8..6d6121eb5 100644 --- a/linux/drivers/media/dvb/dvb-core/dmxdev.c +++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c @@ -244,19 +244,13 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, { struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; - int ret; - if (dmxdev->exit) { - mutex_unlock(&dmxdev->mutex); + if (dmxdev->exit) return -ENODEV; - } - //mutex_lock(&dmxdev->mutex); - ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, - file->f_flags & O_NONBLOCK, - buf, count, ppos); - //mutex_unlock(&dmxdev->mutex); - return ret; + return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, + file->f_flags & O_NONBLOCK, + buf, count, ppos); } static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, -- cgit v1.2.3 From 63e95e82206a96da300f95921d97fbd58dd2246c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 20:39:27 +0000 Subject: radio-mr800.c: missing mutex include From: Alessio Igor Bogani radio-mr800.c uses struct mutex, so while seems to be pulled in indirectly by one of the headers it already includes, the right thing is to include it directly. Signed-off-by: Alessio Igor Bogani Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-mr800.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index 93d5a7aa6..5ff444cee 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -64,6 +64,7 @@ #include #include #include /* for KERNEL_VERSION MACRO */ +#include #include "compat.h" /* driver and module definitions */ -- cgit v1.2.3 From e420aed19a5f4a2715733f2a450e8958fa7e2638 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 May 2009 19:48:07 +0000 Subject: ir-kbd-i2c: Don't use i2c_client.name for our own needs From: Jean Delvare In the standard device driver binding model, the name field of struct i2c_client is used to match devices to their drivers, so we must stop using it for internal purposes. Define a separate field in struct IR_i2c as a replacement, and use it. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-input.c | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 10 +++++----- linux/drivers/media/video/em28xx/em28xx-input.c | 2 +- linux/drivers/media/video/ir-kbd-i2c.c | 5 +++-- linux/drivers/media/video/saa7134/saa7134-input.c | 12 ++++++------ 5 files changed, 16 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-input.c b/linux/drivers/media/video/cx231xx/cx231xx-input.c index 04d954cca..3171b0177 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-input.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-input.c @@ -37,7 +37,7 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); #define i2cdprintk(fmt, arg...) \ if (ir_debug) { \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ } #define dprintk(fmt, arg...) \ diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 1dff7528a..60aa57660 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1449,13 +1449,13 @@ struct em28xx_board em28xx_boards[] = { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AUDIO_SRC_LINE, - .gpio = terratec_av350_unmute_gpio, + .gpio = terratec_av350_unmute_gpio, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AUDIO_SRC_LINE, - .gpio = terratec_av350_unmute_gpio, + .gpio = terratec_av350_unmute_gpio, } }, }, }; @@ -1998,19 +1998,19 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) case (EM2820_BOARD_TERRATEC_CINERGY_250): ir->ir_codes = ir_codes_em_terratec; ir->get_key = em28xx_get_key_terratec; - snprintf(ir->c.name, sizeof(ir->c.name), + snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Terratec)"); break; case (EM2820_BOARD_PINNACLE_USB_2): ir->ir_codes = ir_codes_pinnacle_grey; ir->get_key = em28xx_get_key_pinnacle_usb_grey; - snprintf(ir->c.name, sizeof(ir->c.name), + snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Pinnacle PCTV)"); break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): ir->ir_codes = ir_codes_hauppauge_new; ir->get_key = em28xx_get_key_em_haup; - snprintf(ir->c.name, sizeof(ir->c.name), + snprintf(ir->name, sizeof(ir->name), "i2c IR (EM2840 Hauppauge)"); break; case (EM2820_BOARD_MSI_VOX_USB_2): diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index 5382a6064..31e80a4f0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -41,7 +41,7 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); #define i2cdprintk(fmt, arg...) \ if (ir_debug) { \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ } #define dprintk(fmt, arg...) \ diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index 7bae57ad3..bfc7afcca 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -346,6 +346,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->c.adapter = adap; ir->c.addr = addr; + snprintf(ir->c.name, sizeof(ir->c.name), "ir-kbd"); i2c_set_clientdata(&ir->c, ir); @@ -419,7 +420,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, } /* Sets name */ - snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); + snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name); ir->ir_codes = ir_codes; /* register i2c device @@ -444,7 +445,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, /* init + register input device */ ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); input_dev->id.bustype = BUS_I2C; - input_dev->name = ir->c.name; + input_dev->name = ir->name; input_dev->phys = ir->phys; err = input_register_device(ir->input); diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 80a4cc23d..372c1cb48 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -60,7 +60,7 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " #define dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) #define i2cdprintk(fmt, arg...) if (ir_debug) \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) + printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg) /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ static int saa7134_rc5_irq(struct saa7134_dev *dev); @@ -697,7 +697,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: case SAA7134_BOARD_PINNACLE_PCTV_310i: - snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); + snprintf(ir->name, sizeof(ir->name), "Pinnacle PCTV"); if (pinnacle_remote == 0) { ir->get_key = get_key_pinnacle_color; ir->ir_codes = ir_codes_pinnacle_color; @@ -707,17 +707,17 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: - snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV"); + snprintf(ir->name, sizeof(ir->name), "Purple TV"); ir->get_key = get_key_purpletv; ir->ir_codes = ir_codes_purpletv; break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: - snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus"); + snprintf(ir->name, sizeof(ir->name), "MSI TV@nywhere Plus"); ir->get_key = get_key_msi_tvanywhere_plus; ir->ir_codes = ir_codes_msi_tvanywhere_plus; break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: - snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); + snprintf(ir->name, sizeof(ir->name), "HVR 1110"); ir->get_key = get_key_hvr1110; ir->ir_codes = ir_codes_hauppauge_new; break; @@ -733,7 +733,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: case SAA7134_BOARD_BEHOLD_H6: - snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV"); + snprintf(ir->name, sizeof(ir->name), "BeholdTV"); ir->get_key = get_key_beholdm6xx; ir->ir_codes = ir_codes_behold; break; -- cgit v1.2.3 From b60f8e0b02ee9d9ef582e9df01eb81e5218baf9e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 May 2009 19:48:50 +0000 Subject: ir-kbd-i2c: Switch to the new-style device binding model From: Jean Delvare Let card drivers probe for IR receiver devices and instantiate them if found. Ultimately it would be better if we could stop probing completely, but I suspect this won't be possible for all card types. There's certainly room for cleanups. For example, some drivers are sharing I2C adapter IDs, so they also had to share the list of I2C addresses being probed for an IR receiver. Now that each driver explicitly says which addresses should be probed, maybe some addresses can be dropped from some drivers. Also, the special cases in saa7134-i2c should probably be handled on a per-board basis. This would be more efficient and less risky than always probing extra addresses on all boards. I'll give it a try later. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-i2c.c | 21 +++ linux/drivers/media/video/cx231xx/cx231xx-cards.c | 11 +- linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 3 + linux/drivers/media/video/cx231xx/cx231xx.h | 1 + linux/drivers/media/video/cx23885/cx23885-i2c.c | 12 ++ linux/drivers/media/video/cx88/cx88-i2c.c | 13 ++ linux/drivers/media/video/em28xx/em28xx-cards.c | 20 ++- linux/drivers/media/video/em28xx/em28xx-i2c.c | 3 + linux/drivers/media/video/em28xx/em28xx-input.c | 6 +- linux/drivers/media/video/em28xx/em28xx.h | 3 +- linux/drivers/media/video/ir-kbd-i2c.c | 200 ++++------------------ linux/drivers/media/video/ivtv/ivtv-i2c.c | 31 +++- linux/drivers/media/video/saa7134/saa7134-i2c.c | 3 + linux/drivers/media/video/saa7134/saa7134-input.c | 86 ++++++++-- linux/drivers/media/video/saa7134/saa7134.h | 1 + 15 files changed, 220 insertions(+), 194 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index bf94551c3..31f2f07d9 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -405,6 +405,27 @@ int __devinit init_bttv_i2c(struct bttv *btv) } if (0 == btv->i2c_rc && i2c_scan) do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client); + + /* Instantiate the IR receiver device, if present */ + if (0 == btv->i2c_rc) { + struct i2c_board_info info; + /* The external IR receiver is at i2c address 0x34 (0x35 for + reads). Future Hauppauge cards will have an internal + receiver at 0x30 (0x31 for reads). In theory, both can be + fitted, and Hauppauge suggest an external overrides an + internal. + + That's why we probe 0x1a (~0x34) first. CB + */ + const unsigned short addr_list[] = { + 0x1a, 0x18, 0x4b, 0x64, 0x30, + I2C_CLIENT_END + }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list); + } return btv->i2c_rc; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index af6169516..88d9efd25 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -282,13 +282,16 @@ static void cx231xx_config_tuner(struct cx231xx *dev) } /* ----------------------------------------------------------------------- */ -void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) +void cx231xx_register_i2c_ir(struct cx231xx *dev) { - if (disable_ir) { - ir->get_key = NULL; + if (disable_ir) return; - } + /* REVISIT: instantiate IR device */ +} + +void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) +{ /* detect & configure */ switch (dev->model) { diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c index d196fe666..6ca190c71 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -540,6 +540,9 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) if (0 == bus->i2c_rc) { if (i2c_scan) cx231xx_do_i2c_scan(dev, &bus->i2c_client); + + /* Instantiate the IR receiver device, if present */ + cx231xx_register_i2c_ir(dev); } else cx231xx_warn("%s: i2c bus %d register FAILED\n", dev->name, bus->nr); diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 21b4023dd..85e098997 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -747,6 +747,7 @@ extern void cx231xx_card_setup(struct cx231xx *dev); extern struct cx231xx_board cx231xx_boards[]; extern struct usb_device_id cx231xx_id_table[]; extern const unsigned int cx231xx_bcount; +void cx231xx_register_i2c_ir(struct cx231xx *dev); void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir); int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index a5d9f7530..4369470a3 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -364,6 +364,18 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) printk(KERN_WARNING "%s: i2c bus %d register FAILED\n", dev->name, bus->nr); + /* Instantiate the IR receiver device, if present */ + if (0 == bus->i2c_rc) { + struct i2c_board_info info; + const unsigned short addr_list[] = { + 0x6b, I2C_CLIENT_END + }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + i2c_new_probed_device(&bus->i2c_adap, &info, addr_list); + } + return bus->i2c_rc; } diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c index 680a8c889..dbd629511 100644 --- a/linux/drivers/media/video/cx88/cx88-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-i2c.c @@ -186,6 +186,19 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) do_i2c_scan(core->name,&core->i2c_client); } else printk("%s: i2c register FAILED\n", core->name); + + /* Instantiate the IR receiver device, if present */ + if (0 == core->i2c_rc) { + struct i2c_board_info info; + const unsigned short addr_list[] = { + 0x18, 0x6b, 0x71, + I2C_CLIENT_END + }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + i2c_new_probed_device(&core->i2c_adap, &info, addr_list); + } return core->i2c_rc; } diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 60aa57660..cca8f1fcd 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1981,13 +1981,23 @@ static int em28xx_hint_board(struct em28xx *dev) } /* ----------------------------------------------------------------------- */ -void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) +void em28xx_register_i2c_ir(struct em28xx *dev) { - if (disable_ir) { - ir->get_key = NULL; - return ; - } + struct i2c_board_info info; + const unsigned short addr_list[] = { + 0x30, 0x47, I2C_CLIENT_END + }; + + if (disable_ir) + return; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); +} + +void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) +{ /* detect & configure */ switch (dev->model) { case (EM2800_BOARD_UNKNOWN): diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 24456cebd..40b17785b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -581,6 +581,9 @@ int em28xx_i2c_register(struct em28xx *dev) if (i2c_scan) em28xx_do_i2c_scan(dev); + /* Instantiate the IR receiver device, if present */ + em28xx_register_i2c_ir(dev); + return 0; } diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index 31e80a4f0..bfe2cb8f6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -86,7 +86,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c, &b, 1)) { + if (1 != i2c_master_recv(ir->c, &b, 1)) { i2cdprintk("read error\n"); return -EIO; } @@ -115,7 +115,7 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char code; /* poll IR chip */ - if (2 != i2c_master_recv(&ir->c, buf, 2)) + if (2 != i2c_master_recv(ir->c, buf, 2)) return -EIO; /* Does eliminate repeated parity code */ @@ -153,7 +153,7 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, /* poll IR chip */ - if (3 != i2c_master_recv(&ir->c, buf, 3)) { + if (3 != i2c_master_recv(ir->c, buf, 3)) { i2cdprintk("read error\n"); return -EIO; } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 1bb4a8242..536be4b1c 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -105,7 +105,7 @@ #define EM2820_BOARD_IODATA_GVMVP_SZ 65 #define EM2880_BOARD_EMPIRE_DUAL_TV 66 #define EM2860_BOARD_TERRATEC_GRABBY 67 -#define EM2860_BOARD_TERRATEC_AV350 68 +#define EM2860_BOARD_TERRATEC_AV350 68 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -652,6 +652,7 @@ extern void em28xx_card_setup(struct em28xx *dev); extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; +void em28xx_register_i2c_ir(struct em28xx *dev); void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); int em28xx_tuner_callback(void *ptr, int component, int command, int arg); void em28xx_release_resources(struct em28xx *dev); diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index bfc7afcca..2408b8327 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -75,7 +75,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, int start, range, toggle, dev, code, ircode; /* poll IR chip */ - if (size != i2c_master_recv(&ir->c,buf,size)) + if (size != i2c_master_recv(ir->c, buf, size)) return -EIO; /* split rc5 data block ... */ @@ -138,7 +138,7 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c,&b,1)) { + if (1 != i2c_master_recv(ir->c, &b, 1)) { dprintk(1,"read error\n"); return -EIO; } @@ -152,7 +152,7 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c,&b,1)) { + if (1 != i2c_master_recv(ir->c, &b, 1)) { dprintk(1,"read error\n"); return -EIO; } @@ -172,7 +172,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char buf[4]; /* poll IR chip */ - if (4 != i2c_master_recv(&ir->c,buf,4)) { + if (4 != i2c_master_recv(ir->c, buf, 4)) { dprintk(1,"read error\n"); return -EIO; } @@ -196,7 +196,7 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c,&b,1)) { + if (1 != i2c_master_recv(ir->c, &b, 1)) { dprintk(1,"read error\n"); return -EIO; } @@ -223,12 +223,12 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char subaddr, key, keygroup; - struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0, + struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, .buf = &subaddr, .len = 1}, - { .addr = ir->c.addr, .flags = I2C_M_RD, + { .addr = ir->c->addr, .flags = I2C_M_RD, .buf = &key, .len = 1} }; subaddr = 0x0d; - if (2 != i2c_transfer(ir->c.adapter, msg, 2)) { + if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { dprintk(1, "read error\n"); return -EIO; } @@ -238,7 +238,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir, subaddr = 0x0b; msg[1].buf = &keygroup; - if (2 != i2c_transfer(ir->c.adapter, msg, 2)) { + if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { dprintk(1, "read error\n"); return -EIO; } @@ -295,7 +295,7 @@ static void ir_work(struct work_struct *work) /* MSI TV@nywhere Plus requires more frequent polling otherwise it will miss some keypresses */ - if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30) + if (ir->c->adapter->id == I2C_HW_SAA7134 && ir->c->addr == 0x30) polling_interval = 50; ir_key_poll(ir); @@ -304,34 +304,15 @@ static void ir_work(struct work_struct *work) /* ----------------------------------------------------------------------- */ -static int ir_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind); -static int ir_detach(struct i2c_client *client); -static int ir_probe(struct i2c_adapter *adap); - -static struct i2c_driver driver = { - .driver = { - .name = "ir-kbd-i2c", - }, - .id = I2C_DRIVERID_INFRARED, - .attach_adapter = ir_probe, - .detach_client = ir_detach, -}; - -static struct i2c_client client_template = -{ - .name = "unset", - .driver = &driver -}; - -static int ir_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) +static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { IR_KEYTAB_TYPE *ir_codes = NULL; char *name; int ir_type; struct IR_i2c *ir; struct input_dev *input_dev; + struct i2c_adapter *adap = client->adapter; + unsigned short addr = client->addr; int err; ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); @@ -341,14 +322,9 @@ static int ir_attach(struct i2c_adapter *adap, int addr, goto err_out_free; } - ir->c = client_template; + ir->c = client; ir->input = input_dev; - - ir->c.adapter = adap; - ir->c.addr = addr; - snprintf(ir->c.name, sizeof(ir->c.name), "ir-kbd"); - - i2c_set_clientdata(&ir->c, ir); + i2c_set_clientdata(client, ir); switch(addr) { case 0x64: @@ -423,24 +399,9 @@ static int ir_attach(struct i2c_adapter *adap, int addr, snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name); ir->ir_codes = ir_codes; - /* register i2c device - * At device register, IR codes may be changed to be - * board dependent. - */ - err = i2c_attach_client(&ir->c); - if (err) - goto err_out_free; - - /* If IR not supported or disabled, unregisters driver */ - if (ir->get_key == NULL) { - err = -ENODEV; - goto err_out_detach; - } - - /* Phys addr can only be set after attaching (for ir->c.dev) */ snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0", - dev_name(&ir->c.adapter->dev), - dev_name(&ir->c.dev)); + dev_name(&adap->dev), + dev_name(&client->dev)); /* init + register input device */ ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); @@ -450,7 +411,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, err = input_register_device(ir->input); if (err) - goto err_out_detach; + goto err_out_free; printk(DEVNAME ": %s detected at %s [%s]\n", ir->input->name, ir->input->phys, adap->name); @@ -465,135 +426,42 @@ static int ir_attach(struct i2c_adapter *adap, int addr, return 0; - err_out_detach: - i2c_detach_client(&ir->c); err_out_free: input_free_device(input_dev); kfree(ir); return err; } -static int ir_detach(struct i2c_client *client) +static int ir_remove(struct i2c_client *client) { struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ cancel_delayed_work_sync(&ir->work); - /* unregister devices */ + /* unregister device */ input_unregister_device(ir->input); - i2c_detach_client(&ir->c); /* free memory */ kfree(ir); return 0; } -static int ir_probe(struct i2c_adapter *adap) -{ - - /* The external IR receiver is at i2c address 0x34 (0x35 for - reads). Future Hauppauge cards will have an internal - receiver at 0x30 (0x31 for reads). In theory, both can be - fitted, and Hauppauge suggest an external overrides an - internal. - - That's why we probe 0x1a (~0x34) first. CB - */ - - static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; - static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, 0x2d, -1 }; - static const int probe_em28XX[] = { 0x30, 0x47, -1 }; - static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 }; - static const int probe_cx23885[] = { 0x6b, -1 }; - const int *probe; - struct i2c_msg msg = { - .flags = I2C_M_RD, - .len = 0, - .buf = NULL, - }; - int i, rc; - - switch (adap->id) { - case I2C_HW_B_BT848: - probe = probe_bttv; - break; - case I2C_HW_B_CX2341X: - probe = probe_bttv; - break; - case I2C_HW_SAA7134: - probe = probe_saa7134; - break; - case I2C_HW_B_EM28XX: - probe = probe_em28XX; - break; - case I2C_HW_B_CX2388x: - probe = probe_cx88; - break; - case I2C_HW_B_CX23885: - probe = probe_cx23885; - break; - default: - return 0; - } - - for (i = 0; -1 != probe[i]; i++) { - msg.addr = probe[i]; - rc = i2c_transfer(adap, &msg, 1); - dprintk(1,"probe 0x%02x @ %s: %s\n", - probe[i], adap->name, - (1 == rc) ? "yes" : "no"); - if (1 == rc) { - ir_attach(adap, probe[i], 0, 0); - return 0; - } - } - - /* Special case for MSI TV@nywhere Plus remote */ - if (adap->id == I2C_HW_SAA7134) { - u8 temp; - - /* MSI TV@nywhere Plus controller doesn't seem to - respond to probes unless we read something from - an existing device. Weird... */ - - msg.addr = 0x50; - rc = i2c_transfer(adap, &msg, 1); - dprintk(1, "probe 0x%02x @ %s: %s\n", - msg.addr, adap->name, - (1 == rc) ? "yes" : "no"); - - /* Now do the probe. The controller does not respond - to 0-byte reads, so we use a 1-byte read instead. */ - msg.addr = 0x30; - msg.len = 1; - msg.buf = &temp; - rc = i2c_transfer(adap, &msg, 1); - dprintk(1, "probe 0x%02x @ %s: %s\n", - msg.addr, adap->name, - (1 == rc) ? "yes" : "no"); - if (1 == rc) - ir_attach(adap, msg.addr, 0, 0); - } - - /* Special case for AVerMedia Cardbus remote */ - if (adap->id == I2C_HW_SAA7134) { - unsigned char subaddr, data; - struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0, - .buf = &subaddr, .len = 1}, - { .addr = 0x40, .flags = I2C_M_RD, - .buf = &data, .len = 1} }; - subaddr = 0x0d; - rc = i2c_transfer(adap, msg, 2); - dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n", - msg[0].addr, subaddr, adap->name, - (2 == rc) ? "yes" : "no"); - if (2 == rc) - ir_attach(adap, msg[0].addr, 0, 0); - } +static const struct i2c_device_id ir_kbd_id[] = { + /* Generic entry for any IR receiver */ + { "ir_video", 0 }, + /* IR device specific entries could be added here */ + { } +}; - return 0; -} +static struct i2c_driver driver = { + .driver = { + .name = "ir-kbd-i2c", + }, + .probe = ir_probe, + .remove = ir_remove, + .id_table = ir_kbd_id, +}; /* ----------------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index 984c73b5e..db3ac27da 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -592,9 +592,11 @@ static struct i2c_client ivtv_i2c_client_template = { .name = "ivtv internal", }; -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter + instantiate IR receiver */ int init_ivtv_i2c(struct ivtv *itv) { + int retval; + IVTV_DEBUG_I2C("i2c init\n"); /* Sanity checks for the I2C hardware arrays. They must be the @@ -634,9 +636,32 @@ int init_ivtv_i2c(struct ivtv *itv) ivtv_setsda(itv, 1); if (itv->options.newi2c > 0) - return i2c_add_adapter(&itv->i2c_adap); + retval = i2c_add_adapter(&itv->i2c_adap); else - return i2c_bit_add_bus(&itv->i2c_adap); + retval = i2c_bit_add_bus(&itv->i2c_adap); + + /* Instantiate the IR receiver device, if present */ + if (retval == 0) { + struct i2c_board_info info; + /* The external IR receiver is at i2c address 0x34 (0x35 for + reads). Future Hauppauge cards will have an internal + receiver at 0x30 (0x31 for reads). In theory, both can be + fitted, and Hauppauge suggest an external overrides an + internal. + + That's why we probe 0x1a (~0x34) first. CB + */ + const unsigned short addr_list[] = { + 0x1a, 0x18, 0x64, 0x30, + I2C_CLIENT_END + }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); + } + + return retval; } void exit_ivtv_i2c(struct ivtv *itv) diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index 3eb60aabe..c934249db 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -444,6 +444,9 @@ int saa7134_i2c_register(struct saa7134_dev *dev) saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata)); if (i2c_scan) do_i2c_scan(dev->name,&dev->i2c_client); + + /* Instantiate the IR receiver device, if present */ + saa7134_probe_i2c_ir(dev); return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 372c1cb48..9b64ea543 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -134,10 +134,10 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, int gpio; /* is needed to access GPIO. Used by the saa_readl macro. */ - struct saa7134_dev *dev = ir->c.adapter->algo_data; + struct saa7134_dev *dev = ir->c->adapter->algo_data; if (dev == NULL) { dprintk("get_key_msi_tvanywhere_plus: " - "gir->c.adapter->algo_data is NULL!\n"); + "gir->c->adapter->algo_data is NULL!\n"); return -EIO; } @@ -156,7 +156,7 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, /* GPIO says there is a button press. Get it. */ - if (1 != i2c_master_recv(&ir->c, &b, 1)) { + if (1 != i2c_master_recv(ir->c, &b, 1)) { i2cdprintk("read error\n"); return -EIO; } @@ -179,7 +179,7 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c,&b,1)) { + if (1 != i2c_master_recv(ir->c, &b, 1)) { i2cdprintk("read error\n"); return -EIO; } @@ -202,7 +202,7 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char buf[5], cod4, code3, code4; /* poll IR chip */ - if (5 != i2c_master_recv(&ir->c,buf,5)) + if (5 != i2c_master_recv(ir->c, buf, 5)) return -EIO; cod4 = buf[4]; @@ -224,7 +224,7 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char data[12]; u32 gpio; - struct saa7134_dev *dev = ir->c.adapter->algo_data; + struct saa7134_dev *dev = ir->c->adapter->algo_data; /* rising SAA7134_GPIO_GPRESCAN reads the status */ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); @@ -235,9 +235,9 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) if (0x400000 & ~gpio) return 0; /* No button press */ - ir->c.addr = 0x5a >> 1; + ir->c->addr = 0x5a >> 1; - if (12 != i2c_master_recv(&ir->c, data, 12)) { + if (12 != i2c_master_recv(ir->c, data, 12)) { i2cdprintk("read error\n"); return -EIO; } @@ -267,7 +267,7 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, unsigned int start = 0,parity = 0,code = 0; /* poll IR chip */ - if (4 != i2c_master_recv(&ir->c, b, 4)) { + if (4 != i2c_master_recv(ir->c, b, 4)) { i2cdprintk("read error\n"); return -EIO; } @@ -686,14 +686,76 @@ void saa7134_input_fini(struct saa7134_dev *dev) dev->remote = NULL; } -void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) +void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { + struct i2c_board_info info; + const unsigned short addr_list[] = { + 0x7a, 0x47, 0x71, 0x2d, + I2C_CLIENT_END + }; + + const unsigned short addr_list_msi[] = { + 0x30, I2C_CLIENT_END + }; + struct i2c_msg msg_msi = { + .addr = 0x50, + .flags = I2C_M_RD, + .len = 0, + .buf = NULL, + }; + + unsigned char subaddr, data; + struct i2c_msg msg_avermedia[] = { { + .addr = 0x40, + .flags = 0, + .len = 1, + .buf = &subaddr, + }, { + .addr = 0x40, + .flags = I2C_M_RD, + .len = 1, + .buf = &data, + } }; + + struct i2c_client *client; + int rc; + if (disable_ir) { - dprintk("Found supported i2c remote, but IR has been disabled\n"); - ir->get_key=NULL; + dprintk("IR has been disabled, not probing for i2c remote\n"); return; } + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + if (client) + return; + + /* MSI TV@nywhere Plus controller doesn't seem to + respond to probes unless we read something from + an existing device. Weird... */ + rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); + dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n", + msg_msi.addr, dev->i2c_adap.name, + (1 == rc) ? "yes" : "no"); + client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list_msi); + if (client) + return; + + /* Special case for AVerMedia Cardbus remote */ + subaddr = 0x0d; + rc = i2c_transfer(&dev->i2c_adap, msg_avermedia, 2); + dprintk(KERN_DEBUG "probe 0x%02x/0x%02x @ %s: %s\n", + msg_avermedia[0].addr, subaddr, dev->i2c_adap.name, + (2 == rc) ? "yes" : "no"); + if (2 == rc) { + info.addr = msg_avermedia[0].addr; + i2c_new_device(&dev->i2c_adap, &info); + } +} + +void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) +{ switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: case SAA7134_BOARD_PINNACLE_PCTV_310i: diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index ae7ba8923..4accee8ff 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -804,6 +804,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status); int saa7134_input_init1(struct saa7134_dev *dev); void saa7134_input_fini(struct saa7134_dev *dev); void saa7134_input_irq(struct saa7134_dev *dev); +void saa7134_probe_i2c_ir(struct saa7134_dev *dev); void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir); void saa7134_ir_stop(struct saa7134_dev *dev); -- cgit v1.2.3 From ff5842e7e95c426abf87bbdb32361c523b1b98f0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 May 2009 19:49:32 +0000 Subject: ir-kbd-i2c: Use initialization data From: Jean Delvare For specific boards, pass initialization data to ir-kbd-i2c instead of modifying the settings after the device is initialized. This is more efficient and easier to read. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 3 - linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 29 ------- linux/drivers/media/video/cx231xx/cx231xx.h | 1 - linux/drivers/media/video/em28xx/em28xx-cards.c | 31 ++++---- linux/drivers/media/video/em28xx/em28xx-i2c.c | 22 ------ linux/drivers/media/video/em28xx/em28xx.h | 1 - linux/drivers/media/video/ir-kbd-i2c.c | 12 ++- linux/drivers/media/video/saa7134/saa7134-i2c.c | 28 ------- linux/drivers/media/video/saa7134/saa7134-input.c | 94 +++++++++++------------ linux/drivers/media/video/saa7134/saa7134.h | 1 - 10 files changed, 72 insertions(+), 150 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index 88d9efd25..68f92da9e 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -288,10 +288,7 @@ void cx231xx_register_i2c_ir(struct cx231xx *dev) return; /* REVISIT: instantiate IR device */ -} -void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) -{ /* detect & configure */ switch (dev->model) { diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c index 6ca190c71..e71005c59 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -424,34 +424,6 @@ static u32 functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; } -/* - * attach_inform() - * gets called when a device attaches to the i2c bus - * does some basic configuration - */ -static int attach_inform(struct i2c_client *client) -{ - struct cx231xx_i2c *bus = i2c_get_adapdata(client->adapter); - struct cx231xx *dev = bus->dev; - - switch (client->addr << 1) { - case 0x8e: - { - struct IR_i2c *ir = i2c_get_clientdata(client); - dprintk1(1, "attach_inform: IR detected (%s).\n", - ir->phys); - cx231xx_set_ir(dev, ir); - break; - } - break; - - default: - break; - } - - return 0; -} - static struct i2c_algorithm cx231xx_algo = { .master_xfer = cx231xx_i2c_xfer, .functionality = functionality, @@ -465,7 +437,6 @@ static struct i2c_adapter cx231xx_adap_template = { .name = "cx231xx", .id = I2C_HW_B_CX231XX, .algo = &cx231xx_algo, - .client_register = attach_inform, }; static struct i2c_client cx231xx_client_template = { diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 85e098997..d3c05186e 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -748,7 +748,6 @@ extern struct cx231xx_board cx231xx_boards[]; extern struct usb_device_id cx231xx_id_table[]; extern const unsigned int cx231xx_bcount; void cx231xx_register_i2c_ir(struct cx231xx *dev); -void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir); int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); /* Provided by cx231xx-input.c */ diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index cca8f1fcd..c765d769b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1984,6 +1984,7 @@ static int em28xx_hint_board(struct em28xx *dev) void em28xx_register_i2c_ir(struct em28xx *dev) { struct i2c_board_info info; + struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x30, 0x47, I2C_CLIENT_END }; @@ -1992,12 +1993,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) return; memset(&info, 0, sizeof(struct i2c_board_info)); + memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); -} -void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) -{ /* detect & configure */ switch (dev->model) { case (EM2800_BOARD_UNKNOWN): @@ -2006,22 +2004,19 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) break; case (EM2800_BOARD_TERRATEC_CINERGY_200): case (EM2820_BOARD_TERRATEC_CINERGY_250): - ir->ir_codes = ir_codes_em_terratec; - ir->get_key = em28xx_get_key_terratec; - snprintf(ir->name, sizeof(ir->name), - "i2c IR (EM28XX Terratec)"); + init_data.ir_codes = ir_codes_em_terratec; + init_data.get_key = em28xx_get_key_terratec; + init_data.name = "i2c IR (EM28XX Terratec)"; break; case (EM2820_BOARD_PINNACLE_USB_2): - ir->ir_codes = ir_codes_pinnacle_grey; - ir->get_key = em28xx_get_key_pinnacle_usb_grey; - snprintf(ir->name, sizeof(ir->name), - "i2c IR (EM28XX Pinnacle PCTV)"); + init_data.ir_codes = ir_codes_pinnacle_grey; + init_data.get_key = em28xx_get_key_pinnacle_usb_grey; + init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): - ir->ir_codes = ir_codes_hauppauge_new; - ir->get_key = em28xx_get_key_em_haup; - snprintf(ir->name, sizeof(ir->name), - "i2c IR (EM2840 Hauppauge)"); + init_data.ir_codes = ir_codes_hauppauge_new; + init_data.get_key = em28xx_get_key_em_haup; + init_data.name = "i2c IR (EM2840 Hauppauge)"; break; case (EM2820_BOARD_MSI_VOX_USB_2): break; @@ -2032,6 +2027,10 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) case (EM2800_BOARD_GRABBEEX_USB2800): break; } + + if (init_data.name) + info.platform_data = &init_data; + i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); } void em28xx_card_setup(struct em28xx *dev) diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 40b17785b..fd6be0e2c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -451,27 +451,6 @@ static u32 functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL; } -/* - * attach_inform() - * gets called when a device attaches to the i2c bus - * does some basic configuration - */ -static int attach_inform(struct i2c_client *client) -{ - struct em28xx *dev = client->adapter->algo_data; - struct IR_i2c *ir = i2c_get_clientdata(client); - - switch (client->addr << 1) { - case 0x60: - case 0x8e: - dprintk1(1, "attach_inform: IR detected (%s).\n", ir->phys); - em28xx_set_ir(dev, ir); - break; - } - - return 0; -} - static struct i2c_algorithm em28xx_algo = { .master_xfer = em28xx_i2c_xfer, .functionality = functionality, @@ -488,7 +467,6 @@ static struct i2c_adapter em28xx_adap_template = { .name = "em28xx", .id = I2C_HW_B_EM28XX, .algo = &em28xx_algo, - .client_register = attach_inform, }; static struct i2c_client em28xx_client_template = { diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 536be4b1c..e4ddc50c5 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -653,7 +653,6 @@ extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; void em28xx_register_i2c_ir(struct em28xx *dev); -void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); int em28xx_tuner_callback(void *ptr, int component, int command, int arg); void em28xx_release_resources(struct em28xx *dev); diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index 2408b8327..6a81e74bb 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -307,7 +307,7 @@ static void ir_work(struct work_struct *work) static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { IR_KEYTAB_TYPE *ir_codes = NULL; - char *name; + const char *name; int ir_type; struct IR_i2c *ir; struct input_dev *input_dev; @@ -395,6 +395,16 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) goto err_out_free; } + /* Let the caller override settings */ + if (client->dev.platform_data) { + const struct IR_i2c_init_data *init_data = + client->dev.platform_data; + + ir_codes = init_data->ir_codes; + name = init_data->name; + ir->get_key = init_data->get_key; + } + /* Sets name */ snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name); ir->ir_codes = ir_codes; diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index c934249db..f5790b72d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -326,33 +326,6 @@ static u32 functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL; } -static int attach_inform(struct i2c_client *client) -{ - struct saa7134_dev *dev = client->adapter->algo_data; - - d1printk( "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); - - /* Am I an i2c remote control? */ - - switch (client->addr) { - case 0x7a: - case 0x47: - case 0x71: - case 0x2d: - case 0x30: - { - struct IR_i2c *ir = i2c_get_clientdata(client); - d1printk("%s i2c IR detected (%s).\n", - client->driver->driver.name, ir->phys); - saa7134_set_i2c_ir(dev,ir); - break; - } - } - - return 0; -} - static struct i2c_algorithm saa7134_algo = { .master_xfer = saa7134_i2c_xfer, .functionality = functionality, @@ -369,7 +342,6 @@ static struct i2c_adapter saa7134_adap_template = { .name = "saa7134", .id = I2C_HW_SAA7134, .algo = &saa7134_algo, - .client_register = attach_inform, }; static struct i2c_client saa7134_client_template = { diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 9b64ea543..d0a68dbfd 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -689,6 +689,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { struct i2c_board_info info; + struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x7a, 0x47, 0x71, 0x2d, I2C_CLIENT_END @@ -726,62 +727,35 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) } memset(&info, 0, sizeof(struct i2c_board_info)); + memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); - if (client) - return; - - /* MSI TV@nywhere Plus controller doesn't seem to - respond to probes unless we read something from - an existing device. Weird... */ - rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); - dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n", - msg_msi.addr, dev->i2c_adap.name, - (1 == rc) ? "yes" : "no"); - client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list_msi); - if (client) - return; - /* Special case for AVerMedia Cardbus remote */ - subaddr = 0x0d; - rc = i2c_transfer(&dev->i2c_adap, msg_avermedia, 2); - dprintk(KERN_DEBUG "probe 0x%02x/0x%02x @ %s: %s\n", - msg_avermedia[0].addr, subaddr, dev->i2c_adap.name, - (2 == rc) ? "yes" : "no"); - if (2 == rc) { - info.addr = msg_avermedia[0].addr; - i2c_new_device(&dev->i2c_adap, &info); - } -} - -void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) -{ switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: case SAA7134_BOARD_PINNACLE_PCTV_310i: - snprintf(ir->name, sizeof(ir->name), "Pinnacle PCTV"); + init_data.name = "Pinnacle PCTV"; if (pinnacle_remote == 0) { - ir->get_key = get_key_pinnacle_color; - ir->ir_codes = ir_codes_pinnacle_color; + init_data.get_key = get_key_pinnacle_color; + init_data.ir_codes = ir_codes_pinnacle_color; } else { - ir->get_key = get_key_pinnacle_grey; - ir->ir_codes = ir_codes_pinnacle_grey; + init_data.get_key = get_key_pinnacle_grey; + init_data.ir_codes = ir_codes_pinnacle_grey; } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: - snprintf(ir->name, sizeof(ir->name), "Purple TV"); - ir->get_key = get_key_purpletv; - ir->ir_codes = ir_codes_purpletv; + init_data.name = "Purple TV"; + init_data.get_key = get_key_purpletv; + init_data.ir_codes = ir_codes_purpletv; break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: - snprintf(ir->name, sizeof(ir->name), "MSI TV@nywhere Plus"); - ir->get_key = get_key_msi_tvanywhere_plus; - ir->ir_codes = ir_codes_msi_tvanywhere_plus; + init_data.name = "MSI TV@nywhere Plus"; + init_data.get_key = get_key_msi_tvanywhere_plus; + init_data.ir_codes = ir_codes_msi_tvanywhere_plus; break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: - snprintf(ir->name, sizeof(ir->name), "HVR 1110"); - ir->get_key = get_key_hvr1110; - ir->ir_codes = ir_codes_hauppauge_new; + init_data.name = "HVR 1110"; + init_data.get_key = get_key_hvr1110; + init_data.ir_codes = ir_codes_hauppauge_new; break; case SAA7134_BOARD_BEHOLD_607FM_MK3: case SAA7134_BOARD_BEHOLD_607FM_MK5: @@ -795,15 +769,39 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: case SAA7134_BOARD_BEHOLD_H6: - snprintf(ir->name, sizeof(ir->name), "BeholdTV"); - ir->get_key = get_key_beholdm6xx; - ir->ir_codes = ir_codes_behold; - break; - default: - dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); + init_data.name = "BeholdTV"; + init_data.get_key = get_key_beholdm6xx; + init_data.ir_codes = ir_codes_behold; break; } + if (init_data.name) + info.platform_data = &init_data; + client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + if (client) + return; + + /* MSI TV@nywhere Plus controller doesn't seem to + respond to probes unless we read something from + an existing device. Weird... */ + rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); + dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n", + msg_msi.addr, dev->i2c_adap.name, + (1 == rc) ? "yes" : "no"); + client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list_msi); + if (client) + return; + + /* Special case for AVerMedia Cardbus remote */ + subaddr = 0x0d; + rc = i2c_transfer(&dev->i2c_adap, msg_avermedia, 2); + dprintk(KERN_DEBUG "probe 0x%02x/0x%02x @ %s: %s\n", + msg_avermedia[0].addr, subaddr, dev->i2c_adap.name, + (2 == rc) ? "yes" : "no"); + if (2 == rc) { + info.addr = msg_avermedia[0].addr; + i2c_new_device(&dev->i2c_adap, &info); + } } static int saa7134_rc5_irq(struct saa7134_dev *dev) diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 4accee8ff..be6763dde 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -805,7 +805,6 @@ int saa7134_input_init1(struct saa7134_dev *dev); void saa7134_input_fini(struct saa7134_dev *dev); void saa7134_input_irq(struct saa7134_dev *dev); void saa7134_probe_i2c_ir(struct saa7134_dev *dev); -void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir); void saa7134_ir_stop(struct saa7134_dev *dev); -- cgit v1.2.3 From 2c8bfee91d5f58d681bf8fe04c2d69ba7f7a6925 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 May 2009 19:50:11 +0000 Subject: ir-kbd-i2c: Don't assume all IR receivers are supported From: Jean Delvare The code in ir_probe makes the dangerous assumption that all IR receivers are supported by the driver. The new i2c model makes it possible for bridge drivers to instantiate IR devices before they are supported, therefore the ir-kbd-i2c drivers must be made more robust to not spam the logs or even crash on unsupported IR devices. Simply, the driver will not bind to the unsupported devices. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index 6a81e74bb..0a18d07c7 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -307,7 +307,7 @@ static void ir_work(struct work_struct *work) static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { IR_KEYTAB_TYPE *ir_codes = NULL; - const char *name; + const char *name = NULL; int ir_type; struct IR_i2c *ir; struct input_dev *input_dev; @@ -389,8 +389,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir_codes = ir_codes_avermedia_cardbus; break; default: - /* shouldn't happen */ - printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr); + dprintk(1, DEVNAME ": Unsupported i2c address 0x%02x\n", addr); err = -ENODEV; goto err_out_free; } @@ -405,6 +404,14 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->get_key = init_data->get_key; } + /* Make sure we are all setup before going on */ + if (!name || !ir->get_key || !ir_codes) { + dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n", + addr); + err = -ENODEV; + goto err_out_free; + } + /* Sets name */ snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name); ir->ir_codes = ir_codes; -- cgit v1.2.3 From 39c428638134709e9d5d9d135db22ff39967175d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 May 2009 19:51:46 +0000 Subject: saa7134: Simplify handling of IR on MSI TV@nywhere Plus From: Jean Delvare Now that we instantiate I2C IR devices explicitly, we can skip probing altogether on boards where the I2C IR device address is known. The MSI TV@nywhere Plus is one of these boards. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-input.c | 28 ++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index d0a68dbfd..3dc600631 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -695,9 +695,6 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) I2C_CLIENT_END }; - const unsigned short addr_list_msi[] = { - 0x30, I2C_CLIENT_END - }; struct i2c_msg msg_msi = { .addr = 0x50, .flags = I2C_M_RD, @@ -751,6 +748,15 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) init_data.name = "MSI TV@nywhere Plus"; init_data.get_key = get_key_msi_tvanywhere_plus; init_data.ir_codes = ir_codes_msi_tvanywhere_plus; + info.addr = 0x30; + /* MSI TV@nywhere Plus controller doesn't seem to + respond to probes unless we read something from + an existing device. Weird... + REVISIT: might no longer be needed */ + rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); + dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n", + msg_msi.addr, dev->i2c_adap.name, + (1 == rc) ? "yes" : "no"); break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: init_data.name = "HVR 1110"; @@ -777,18 +783,14 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) if (init_data.name) info.platform_data = &init_data; - client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); - if (client) + /* No need to probe if address is known */ + if (info.addr) { + i2c_new_device(&dev->i2c_adap, &info); return; + } - /* MSI TV@nywhere Plus controller doesn't seem to - respond to probes unless we read something from - an existing device. Weird... */ - rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); - dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n", - msg_msi.addr, dev->i2c_adap.name, - (1 == rc) ? "yes" : "no"); - client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list_msi); + /* Address not known, fallback to probing */ + client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); if (client) return; -- cgit v1.2.3 From d7c1afcf9e6a72c1c7b85032e33a4a45091694b6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 May 2009 19:52:44 +0000 Subject: saa7134: Simplify handling of IR on AVerMedia Cardbus E506R From: Jean Delvare Now that we instantiate I2C IR devices explicitly, we can skip probing altogether on boards where the I2C IR device address is known. The AVerMedia Cardbus E506R is one of these boards. Signed-off-by: Jean Delvare Tested-by: Oldrich Jedlicka Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-input.c | 33 ++++------------------- 1 file changed, 5 insertions(+), 28 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 3dc600631..36913d22b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -702,20 +702,6 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) .buf = NULL, }; - unsigned char subaddr, data; - struct i2c_msg msg_avermedia[] = { { - .addr = 0x40, - .flags = 0, - .len = 1, - .buf = &subaddr, - }, { - .addr = 0x40, - .flags = I2C_M_RD, - .len = 1, - .buf = &data, - } }; - - struct i2c_client *client; int rc; if (disable_ir) { @@ -779,6 +765,10 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) init_data.get_key = get_key_beholdm6xx; init_data.ir_codes = ir_codes_behold; break; + case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: + case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + info.addr = 0x40; + break; } if (init_data.name) @@ -790,20 +780,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) } /* Address not known, fallback to probing */ - client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); - if (client) - return; - - /* Special case for AVerMedia Cardbus remote */ - subaddr = 0x0d; - rc = i2c_transfer(&dev->i2c_adap, msg_avermedia, 2); - dprintk(KERN_DEBUG "probe 0x%02x/0x%02x @ %s: %s\n", - msg_avermedia[0].addr, subaddr, dev->i2c_adap.name, - (2 == rc) ? "yes" : "no"); - if (2 == rc) { - info.addr = msg_avermedia[0].addr; - i2c_new_device(&dev->i2c_adap, &info); - } + i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); } static int saa7134_rc5_irq(struct saa7134_dev *dev) -- cgit v1.2.3 From eeb337b881232de30fee5db9fb1899f381ca4249 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 May 2009 19:55:13 +0000 Subject: ivtv: Probe more I2C addresses for IR devices From: Jean Delvare Probe I2C addresses 0x71 and 0x6b for IR receiver devices (for the PVR150 and Adaptec cards, respectively.) Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ivtv/ivtv-i2c.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index db3ac27da..0d18c2220 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -652,7 +652,12 @@ int init_ivtv_i2c(struct ivtv *itv) That's why we probe 0x1a (~0x34) first. CB */ const unsigned short addr_list[] = { - 0x1a, 0x18, 0x64, 0x30, + 0x1a, /* Hauppauge IR external */ + 0x18, /* Hauppauge IR internal */ + 0x71, /* Hauppauge IR (PVR150) */ + 0x64, /* Pixelview IR */ + 0x30, /* KNC ONE IR */ + 0x6b, /* Adaptec IR */ I2C_CLIENT_END }; -- cgit v1.2.3 From 71d712e8f23494d0869cbc8e93b0dcf4891cc45a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 13 May 2009 19:56:20 +0000 Subject: pvrusb2: Instantiate ir_video I2C device by default From: Jean Delvare Now that the ir-kbd-i2c driver has been converted to a new-style i2c driver, we can instantiate the ir_video I2C device by default. The pvr2_disable_ir_video is kept to disable the IR receiver, either because the user doesn't use it, or for debugging purpose. Signed-off-by: Jean Delvare Acked-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 28463489a..694e51f58 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -43,7 +43,7 @@ static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 }; module_param_array(ir_mode, int, NULL, 0444); MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); -static int pvr2_disable_ir_video = 1; +static int pvr2_disable_ir_video; module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(disable_autoload_ir_video, -- cgit v1.2.3 From 67244363bf89cf9f2e5669d2ec3c582cd07a321c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 15 May 2009 17:32:04 +0000 Subject: patch: s2255drv: adding V4L2_MODE_HIGHQUALITY From: Dean Anderson Adding V4L2_MODE_HIGHQUALITY feature. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/s2255drv.c | 48 +++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index 8a939387a..203f6e3ff 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -110,6 +110,8 @@ #define SCALE_4CIFS 1 /* 640x480(NTSC) or 704x576(PAL) */ #define SCALE_2CIFS 2 /* 640x240(NTSC) or 704x288(PAL) */ #define SCALE_1CIFS 3 /* 320x240(NTSC) or 352x288(PAL) */ +/* SCALE_4CIFSI is the 2 fields interpolated into one */ +#define SCALE_4CIFSI 4 /* 640x480(NTSC) or 704x576(PAL) high quality */ #define COLOR_YUVPL 1 /* YUV planar */ #define COLOR_YUVPK 2 /* YUV packed */ @@ -239,6 +241,8 @@ struct s2255_dev { struct s2255_mode mode[MAX_CHANNELS]; /* jpeg compression */ struct v4l2_jpegcompression jc[MAX_CHANNELS]; + /* capture parameters (for high quality mode full size) */ + struct v4l2_captureparm cap_parm[MAX_CHANNELS]; const struct s2255_fmt *cur_fmt[MAX_CHANNELS]; int cur_frame[MAX_CHANNELS]; int last_frame[MAX_CHANNELS]; @@ -1021,9 +1025,16 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->type = f->type; norm = norm_minw(fh->dev->vdev[fh->channel]); if (fh->width > norm_minw(fh->dev->vdev[fh->channel])) { - if (fh->height > norm_minh(fh->dev->vdev[fh->channel])) - fh->mode.scale = SCALE_4CIFS; - else + if (fh->height > norm_minh(fh->dev->vdev[fh->channel])) { + if (fh->dev->cap_parm[fh->channel].capturemode & + V4L2_MODE_HIGHQUALITY) { + fh->mode.scale = SCALE_4CIFSI; + dprintk(2, "scale 4CIFSI\n"); + } else { + fh->mode.scale = SCALE_4CIFS; + dprintk(2, "scale 4CIFS\n"); + } + } else fh->mode.scale = SCALE_2CIFS; } else { @@ -1124,6 +1135,7 @@ static u32 get_transfer_size(struct s2255_mode *mode) if (mode->format == FORMAT_NTSC) { switch (mode->scale) { case SCALE_4CIFS: + case SCALE_4CIFSI: linesPerFrame = NUM_LINES_4CIFS_NTSC * 2; pixelsPerLine = LINE_SZ_4CIFS_NTSC; break; @@ -1141,6 +1153,7 @@ static u32 get_transfer_size(struct s2255_mode *mode) } else if (mode->format == FORMAT_PAL) { switch (mode->scale) { case SCALE_4CIFS: + case SCALE_4CIFSI: linesPerFrame = NUM_LINES_4CIFS_PAL * 2; pixelsPerLine = LINE_SZ_4CIFS_PAL; break; @@ -1496,6 +1509,33 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, dprintk(2, "setting jpeg quality %d\n", jc->quality); return 0; } + +static int vidioc_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *sp) +{ + struct s2255_fh *fh = priv; + struct s2255_dev *dev = fh->dev; + if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + sp->parm.capture.capturemode = dev->cap_parm[fh->channel].capturemode; + dprintk(2, "getting parm %d\n", sp->parm.capture.capturemode); + return 0; +} + +static int vidioc_s_parm(struct file *file, void *priv, + struct v4l2_streamparm *sp) +{ + struct s2255_fh *fh = priv; + struct s2255_dev *dev = fh->dev; + + if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + dev->cap_parm[fh->channel].capturemode = sp->parm.capture.capturemode; + dprintk(2, "setting param capture mode %d\n", + sp->parm.capture.capturemode); + return 0; +} static int s2255_open(struct file *file) { int minor = video_devdata(file)->minor; @@ -1787,6 +1827,8 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { #endif .vidioc_s_jpegcomp = vidioc_s_jpegcomp, .vidioc_g_jpegcomp = vidioc_g_jpegcomp, + .vidioc_s_parm = vidioc_s_parm, + .vidioc_g_parm = vidioc_g_parm, }; static struct video_device template = { -- cgit v1.2.3 From 713eb7e466a32a7c315c799beb83a9d6c51e0e03 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 18 May 2009 02:13:13 +0000 Subject: saa7134-video.c: poll method lose race condition From: figo.zhang saa7134-video.c: poll method lose race condition Signed-off-by: Figo.zhang Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-video.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 5f68bed54..26f1727e6 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1423,11 +1423,13 @@ video_poll(struct file *file, struct poll_table_struct *wait) { struct saa7134_fh *fh = file->private_data; struct videobuf_buffer *buf = NULL; + unsigned int rc = 0; if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) return videobuf_poll_stream(file, &fh->vbi, wait); if (res_check(fh,RESOURCE_VIDEO)) { + mutex_lock(&fh->cap.vb_lock); if (!list_empty(&fh->cap.stream)) buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream); } else { @@ -1446,13 +1448,14 @@ video_poll(struct file *file, struct poll_table_struct *wait) } if (!buf) - return POLLERR; + rc = POLLERR; poll_wait(file, &buf->done, wait); if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - return 0; + rc = POLLIN|POLLRDNORM; + mutex_unlock(&fh->cap.vb_lock); + return rc; err: mutex_unlock(&fh->cap.vb_lock); -- cgit v1.2.3 From 8e9cc981e8c7b756ee8da597dbd9861e86f53cbf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 18 May 2009 02:31:55 +0000 Subject: minor have assigned value twice From: figo.zhang The variable minor have assigned value twice, the first time is in the initial "video_device" data struct in those drivers, pls see saa7134-video.c,line 2503. --- Signed-off-by: Figo.zhang Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-driver.c | 1 - linux/drivers/media/video/cx23885/cx23885-417.c | 1 - linux/drivers/media/video/cx88/cx88-core.c | 1 - linux/drivers/media/video/saa7134/saa7134-core.c | 1 - 4 files changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 622807b54..8d2075186 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -4198,7 +4198,6 @@ static struct video_device *vdev_init(struct bttv *btv, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; vfd->v4l2_dev = &btv->c.v4l2_dev; vfd->release = video_device_release; vfd->debug = bttv_debug; diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index 574cdb385..9974d9a78 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -1749,7 +1749,6 @@ static struct video_device *cx23885_video_dev_alloc( if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx23885_boards[tsport->dev->board].name); vfd->parent = &pci->dev; diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index 39cbd152a..fddba2d51 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -1057,7 +1057,6 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; vfd->v4l2_dev = &core->v4l2_dev; vfd->parent = &pci->dev; vfd->release = video_device_release; diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 69a214417..dc692d7a7 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -836,7 +836,6 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; vfd->debug = video_debug; -- cgit v1.2.3